summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Help/manual/cmake-compile-features.7.rst20
-rw-r--r--Help/release/3.9.rst7
-rw-r--r--Modules/CMakeCUDAInformation.cmake13
-rw-r--r--Modules/CheckIPOSupported.cmake18
-rw-r--r--Modules/Compiler/Clang.cmake4
-rw-r--r--Modules/Compiler/GNU.cmake6
-rw-r--r--Modules/Compiler/QCC.cmake4
-rw-r--r--Modules/FindPkgConfig.cmake8
-rw-r--r--Modules/Platform/Linux-Intel.cmake8
-rw-r--r--Modules/Platform/Windows-NVIDIA-CUDA.cmake12
-rw-r--r--README.rst8
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/cmGeneratorTarget.cxx23
-rw-r--r--Source/cmGeneratorTarget.h5
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx2
-rw-r--r--Source/cmLocalGenerator.cxx4
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx2
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx6
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx4
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx58
-rw-r--r--Source/cmakemain.cxx16
-rw-r--r--Tests/CMakeLists.txt1
-rw-r--r--Tests/CSharpLinkToCxx/CMakeLists.txt17
-rw-r--r--Tests/CSharpLinkToCxx/cli.cpp10
-rw-r--r--Tests/CSharpLinkToCxx/cli.hpp10
-rw-r--r--Tests/CSharpLinkToCxx/csharp.cs16
-rw-r--r--Tests/CudaOnly/SeparateCompilation/CMakeLists.txt4
-rw-r--r--Tests/CudaOnly/WithDefs/CMakeLists.txt1
-rw-r--r--Tests/CudaOnly/WithDefs/main.notcu4
-rw-r--r--Tests/RunCMake/CMP0069/CMP0069-NEW-cmake.cmake2
-rw-r--r--Tests/RunCMake/CMP0069/CMP0069-NEW-compiler.cmake4
-rw-r--r--Tests/RunCMake/CMP0069/CMP0069-NEW-generator.cmake4
-rw-r--r--Tests/RunCMake/CMP0069/CMP0069-WARN.cmake2
-rw-r--r--Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake-stderr.txt2
-rw-r--r--Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake.cmake2
-rw-r--r--Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-stderr.txt2
-rw-r--r--Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler.cmake4
-rw-r--r--Tests/RunCMake/CheckIPOSupported/not-supported-by-generator.cmake4
-rwxr-xr-xUtilities/Scripts/update-curl.bash2
-rwxr-xr-xUtilities/Scripts/update-expat.bash5
-rw-r--r--Utilities/cmcurl/CMakeLists.txt81
-rw-r--r--Utilities/cmcurl/include/curl/curl.h7
-rw-r--r--Utilities/cmcurl/include/curl/curlver.h12
-rw-r--r--Utilities/cmcurl/include/curl/typecheck-gcc.h160
-rw-r--r--Utilities/cmcurl/lib/asyn-ares.c12
-rw-r--r--Utilities/cmcurl/lib/asyn-thread.c14
-rw-r--r--Utilities/cmcurl/lib/conncache.c8
-rw-r--r--Utilities/cmcurl/lib/connect.c6
-rw-r--r--Utilities/cmcurl/lib/curl_endian.c114
-rw-r--r--Utilities/cmcurl/lib/curl_endian.h26
-rw-r--r--Utilities/cmcurl/lib/curl_md4.h8
-rw-r--r--Utilities/cmcurl/lib/curl_ntlm_core.c10
-rw-r--r--Utilities/cmcurl/lib/curl_rtmp.c1
-rw-r--r--Utilities/cmcurl/lib/curl_sasl.c7
-rw-r--r--Utilities/cmcurl/lib/curl_setup.h14
-rw-r--r--Utilities/cmcurl/lib/curl_setup_once.h2
-rw-r--r--Utilities/cmcurl/lib/dotdot.c3
-rw-r--r--Utilities/cmcurl/lib/easy.c18
-rw-r--r--Utilities/cmcurl/lib/file.c24
-rw-r--r--Utilities/cmcurl/lib/fileinfo.c14
-rw-r--r--Utilities/cmcurl/lib/fileinfo.h12
-rw-r--r--Utilities/cmcurl/lib/formdata.c45
-rw-r--r--Utilities/cmcurl/lib/ftp.c37
-rw-r--r--Utilities/cmcurl/lib/ftplistparser.c49
-rw-r--r--Utilities/cmcurl/lib/hash.c14
-rw-r--r--Utilities/cmcurl/lib/hash.h1
-rw-r--r--Utilities/cmcurl/lib/hostip.c8
-rw-r--r--Utilities/cmcurl/lib/http.c89
-rw-r--r--Utilities/cmcurl/lib/http2.c64
-rw-r--r--Utilities/cmcurl/lib/http_proxy.c73
-rw-r--r--Utilities/cmcurl/lib/http_proxy.h7
-rw-r--r--Utilities/cmcurl/lib/if2ip.c2
-rw-r--r--Utilities/cmcurl/lib/krb5.c14
-rw-r--r--Utilities/cmcurl/lib/ldap.c101
-rw-r--r--Utilities/cmcurl/lib/llist.c35
-rw-r--r--Utilities/cmcurl/lib/llist.h15
-rw-r--r--Utilities/cmcurl/lib/md4.c12
-rw-r--r--Utilities/cmcurl/lib/md5.c2
-rw-r--r--Utilities/cmcurl/lib/memdebug.c22
-rw-r--r--Utilities/cmcurl/lib/mprintf.c8
-rw-r--r--Utilities/cmcurl/lib/multi.c164
-rw-r--r--Utilities/cmcurl/lib/multihandle.h1
-rw-r--r--Utilities/cmcurl/lib/multiif.h7
-rw-r--r--Utilities/cmcurl/lib/pingpong.c15
-rw-r--r--Utilities/cmcurl/lib/pipeline.c56
-rw-r--r--Utilities/cmcurl/lib/rand.c63
-rw-r--r--Utilities/cmcurl/lib/rand.h12
-rw-r--r--Utilities/cmcurl/lib/sendf.c77
-rw-r--r--Utilities/cmcurl/lib/smb.c2
-rw-r--r--Utilities/cmcurl/lib/smtp.c2
-rw-r--r--Utilities/cmcurl/lib/speedcheck.c2
-rw-r--r--Utilities/cmcurl/lib/ssh.c38
-rw-r--r--Utilities/cmcurl/lib/telnet.c100
-rw-r--r--Utilities/cmcurl/lib/tftp.c8
-rw-r--r--Utilities/cmcurl/lib/timeval.c6
-rw-r--r--Utilities/cmcurl/lib/timeval.h2
-rw-r--r--Utilities/cmcurl/lib/transfer.c127
-rw-r--r--Utilities/cmcurl/lib/url.c156
-rw-r--r--Utilities/cmcurl/lib/urldata.h52
-rw-r--r--Utilities/cmcurl/lib/vauth/digest.c19
-rw-r--r--Utilities/cmcurl/lib/vauth/ntlm.c14
-rw-r--r--Utilities/cmcurl/lib/vtls/cyassl.c64
-rw-r--r--Utilities/cmcurl/lib/vtls/darwinssl.c158
-rw-r--r--Utilities/cmcurl/lib/vtls/darwinssl.h24
-rw-r--r--Utilities/cmcurl/lib/vtls/gtls.c19
-rw-r--r--Utilities/cmcurl/lib/vtls/mbedtls.c13
-rw-r--r--Utilities/cmcurl/lib/vtls/nss.c168
-rw-r--r--Utilities/cmcurl/lib/vtls/openssl.c20
-rw-r--r--Utilities/cmcurl/lib/vtls/schannel.c15
-rw-r--r--Utilities/cmcurl/lib/x509asn1.c1
-rw-r--r--Utilities/cmexpat/COPYING5
-rw-r--r--Utilities/cmexpat/README4
-rw-r--r--Utilities/cmexpat/lib/expat.h30
-rw-r--r--Utilities/cmexpat/lib/expat_external.h5
-rw-r--r--Utilities/cmexpat/lib/siphash.h354
-rw-r--r--Utilities/cmexpat/lib/winconfig.h19
-rw-r--r--Utilities/cmexpat/lib/xmlparse.c611
-rw-r--r--Utilities/cmexpat/lib/xmlrole.c10
-rw-r--r--Utilities/cmexpat/lib/xmltok.c34
-rw-r--r--Utilities/cmexpat/lib/xmltok_impl.c4
120 files changed, 2669 insertions, 1289 deletions
diff --git a/Help/manual/cmake-compile-features.7.rst b/Help/manual/cmake-compile-features.7.rst
index fa2aa8dece..012439500b 100644
--- a/Help/manual/cmake-compile-features.7.rst
+++ b/Help/manual/cmake-compile-features.7.rst
@@ -334,7 +334,7 @@ versions specified for each:
* ``AppleClang``: Apple Clang for Xcode versions 4.4 though 6.2.
* ``Clang``: Clang compiler versions 2.9 through 3.4.
* ``GNU``: GNU compiler versions 4.4 through 5.0.
-* ``MSVC``: Microsoft Visual Studio versions 2010 through 2015.
+* ``MSVC``: Microsoft Visual Studio versions 2010 through 2017.
* ``SunPro``: Oracle SolarisStudio versions 12.4 through 12.5.
* ``Intel``: Intel compiler versions 12.1 through 17.0.
@@ -343,9 +343,25 @@ and :prop_gbl:`compile features <CMAKE_C_KNOWN_FEATURES>` available from
the following :variable:`compiler ids <CMAKE_<LANG>_COMPILER_ID>` as of the
versions specified for each:
-* all compilers and versions listed above for C++
+* all compilers and versions listed above for C++.
* ``GNU``: GNU compiler versions 3.4 through 5.0.
+CMake is currently aware of the :prop_tgt:`C++ standards <CXX_STANDARD>` and
+their associated meta-features (e.g. ``cxx_std_11``) available from the
+following :variable:`compiler ids <CMAKE_<LANG>_COMPILER_ID>` as of the
+versions specified for each:
+
+* ``Cray``: Cray Compiler Environment version 8.1 through 8.5.8.
+* ``PGI``: PGI version 12.10 through 17.5.
+* ``XL``: IBM XL version 10.1 through 13.1.5.
+
+CMake is currently aware of the :prop_tgt:`C standards <C_STANDARD>` and
+their associated meta-features (e.g. ``c_std_99``) available from the
+following :variable:`compiler ids <CMAKE_<LANG>_COMPILER_ID>` as of the
+versions specified for each:
+
+* all compilers and versions listed above with only meta-features for C++.
+
CMake is currently aware of the :prop_tgt:`CUDA standards <CUDA_STANDARD>`
from the following :variable:`compiler ids <CMAKE_<LANG>_COMPILER_ID>` as of the
versions specified for each:
diff --git a/Help/release/3.9.rst b/Help/release/3.9.rst
index 333ba9e11d..c31f533986 100644
--- a/Help/release/3.9.rst
+++ b/Help/release/3.9.rst
@@ -16,6 +16,13 @@ Languages
* ``CUDA`` is now supported by the :ref:`Visual Studio Generators`
for VS 2010 and above. This complements the existing support by the
:ref:`Makefile Generators` and the :generator:`Ninja` generator.
+ CUDA 8.0.61 or higher is recommended due to known bugs in the VS
+ integration by earlier versions.
+
+* CMake is now aware of the :prop_tgt:`C++ standards <CXX_STANDARD>` and
+ :prop_tgt:`C standards <C_STANDARD>` and their associated meta-features for
+ the following :variable:`compiler ids <CMAKE_<LANG>_COMPILER_ID>`: ``Cray``,
+ ``PGI``, and ``XL``.
Generators
----------
diff --git a/Modules/CMakeCUDAInformation.cmake b/Modules/CMakeCUDAInformation.cmake
index 1c48159dd3..780e953d08 100644
--- a/Modules/CMakeCUDAInformation.cmake
+++ b/Modules/CMakeCUDAInformation.cmake
@@ -186,16 +186,25 @@ if(NOT CMAKE_CUDA_LINK_EXECUTABLE)
"<CMAKE_CUDA_HOST_LINK_LAUNCHER> <CMAKE_CUDA_LINK_FLAGS> <LINK_FLAGS> <OBJECTS> -o <TARGET> <LINK_LIBRARIES>${__IMPLICT_LINKS}")
endif()
+if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "8.0.0")
+ set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "-Wno-deprecated-gpu-targets")
+else()
+ set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "")
+endif()
+
+
#These are used when linking relocatable (dc) cuda code
if(NOT CMAKE_CUDA_DEVICE_LINK_LIBRARY)
set(CMAKE_CUDA_DEVICE_LINK_LIBRARY
- "<CMAKE_CUDA_COMPILER> <CMAKE_CUDA_LINK_FLAGS> <LANGUAGE_COMPILE_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
+ "<CMAKE_CUDA_COMPILER> <CMAKE_CUDA_LINK_FLAGS> <LANGUAGE_COMPILE_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
endif()
if(NOT CMAKE_CUDA_DEVICE_LINK_EXECUTABLE)
set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE
- "<CMAKE_CUDA_COMPILER> <FLAGS> <CMAKE_CUDA_LINK_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
+ "<CMAKE_CUDA_COMPILER> <FLAGS> <CMAKE_CUDA_LINK_FLAGS> ${CMAKE_CUDA_COMPILE_OPTIONS_PIC} ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES>")
endif()
+unset(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS)
+
mark_as_advanced(
CMAKE_CUDA_FLAGS
CMAKE_CUDA_FLAGS_RELEASE
diff --git a/Modules/CheckIPOSupported.cmake b/Modules/CheckIPOSupported.cmake
index 6bbde135ea..e04ab1c543 100644
--- a/Modules/CheckIPOSupported.cmake
+++ b/Modules/CheckIPOSupported.cmake
@@ -207,15 +207,17 @@ function(check_ipo_supported)
endif()
endif()
- if(NOT _CMAKE_IPO_SUPPORTED_BY_CMAKE)
- _ipo_not_supported("CMake doesn't support IPO for current compiler")
- return()
- endif()
+ foreach(lang ${languages})
+ if(NOT _CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE)
+ _ipo_not_supported("CMake doesn't support IPO for current ${lang} compiler")
+ return()
+ endif()
- if(NOT _CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER)
- _ipo_not_supported("Compiler doesn't support IPO")
- return()
- endif()
+ if(NOT _CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER)
+ _ipo_not_supported("${lang} compiler doesn't support IPO")
+ return()
+ endif()
+ endforeach()
if(CMAKE_GENERATOR MATCHES "^Visual Studio ")
_ipo_not_supported("CMake doesn't support IPO for current generator")
diff --git a/Modules/Compiler/Clang.cmake b/Modules/Compiler/Clang.cmake
index ef7ff2ebe3..7d476f965f 100644
--- a/Modules/Compiler/Clang.cmake
+++ b/Modules/Compiler/Clang.cmake
@@ -30,8 +30,8 @@ else()
set(CMAKE_${lang}_COMPILE_OPTIONS_EXTERNAL_TOOLCHAIN "--gcc-toolchain=")
endif()
- set(_CMAKE_IPO_SUPPORTED_BY_CMAKE YES)
- set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
+ set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
+ set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
string(COMPARE EQUAL "${CMAKE_${lang}_COMPILER_ID}" "AppleClang" __is_apple_clang)
diff --git a/Modules/Compiler/GNU.cmake b/Modules/Compiler/GNU.cmake
index e2739a8a58..675e505347 100644
--- a/Modules/Compiler/GNU.cmake
+++ b/Modules/Compiler/GNU.cmake
@@ -48,14 +48,14 @@ macro(__compiler_gnu lang)
set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-isystem ")
endif()
- set(_CMAKE_IPO_SUPPORTED_BY_CMAKE YES)
- set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
+ set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
+ set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
# '-flto' introduced since GCC 4.5:
# * https://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/Option-Summary.html (no)
# * https://gcc.gnu.org/onlinedocs/gcc-4.5.4/gcc/Option-Summary.html (yes)
if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 4.5)
- set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
+ set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
set(__lto_flags -flto)
if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 4.7)
diff --git a/Modules/Compiler/QCC.cmake b/Modules/Compiler/QCC.cmake
index 695a138fd4..0da7050ba5 100644
--- a/Modules/Compiler/QCC.cmake
+++ b/Modules/Compiler/QCC.cmake
@@ -13,8 +13,8 @@ macro(__compiler_qcc lang)
set(CMAKE_INCLUDE_SYSTEM_FLAG_${lang} "-Wp,-isystem,")
set(CMAKE_DEPFILE_FLAGS_${lang} "-Wc,-MD,<DEPFILE>,-MT,<OBJECT>,-MF,<DEPFILE>")
- set(_CMAKE_IPO_SUPPORTED_BY_CMAKE NO)
- set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
+ set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE NO)
+ set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
unset(CMAKE_${lang}_COMPILE_OPTIONS_IPO)
unset(CMAKE_${lang}_ARCHIVE_CREATE_IPO)
diff --git a/Modules/FindPkgConfig.cmake b/Modules/FindPkgConfig.cmake
index 12a5ded835..a5357fa1c7 100644
--- a/Modules/FindPkgConfig.cmake
+++ b/Modules/FindPkgConfig.cmake
@@ -65,7 +65,7 @@ macro(_pkgconfig_invoke _pkglist _prefix _varname _regexp)
set(_pkgconfig_${_varname} "")
_pkgconfig_unset(${_prefix}_${_varname})
else()
- string(REGEX REPLACE "[\r\n]" " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}")
+ string(REGEX REPLACE "[\r\n]" " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}")
if (NOT ${_regexp} STREQUAL "")
string(REGEX REPLACE "${_regexp}" " " _pkgconfig_invoke_result "${_pkgconfig_invoke_result}")
@@ -86,6 +86,9 @@ endmacro()
pkg_get_variable(<RESULT> <MODULE> <VARIABLE>)
+ If multiple values are returned variable will contain a
+ :ref:`;-list <CMake Language Lists>`.
+
For example:
.. code-block:: cmake
@@ -524,6 +527,9 @@ endmacro()
<XPREFIX> = <PREFIX> for common case
<XPREFIX> = <PREFIX>_STATIC for static linking
+ Every variable containing multiple values will be a
+ :ref:`;-list <CMake Language Lists>`.
+
There are some special variables whose prefix depends on the count of
given modules. When there is only one module, <PREFIX> stays
unchanged. When there are multiple modules, the prefix will be
diff --git a/Modules/Platform/Linux-Intel.cmake b/Modules/Platform/Linux-Intel.cmake
index 6e2978afa9..ee9aac26a9 100644
--- a/Modules/Platform/Linux-Intel.cmake
+++ b/Modules/Platform/Linux-Intel.cmake
@@ -30,7 +30,7 @@ macro(__linux_compiler_intel lang)
# executables that use dlopen but do not set ENABLE_EXPORTS.
set(CMAKE_SHARED_LIBRARY_LINK_${lang}_FLAGS "-rdynamic")
- set(_CMAKE_IPO_SUPPORTED_BY_CMAKE YES)
+ set(_CMAKE_${lang}_IPO_SUPPORTED_BY_CMAKE YES)
if(XIAR)
# INTERPROCEDURAL_OPTIMIZATION
@@ -38,10 +38,10 @@ macro(__linux_compiler_intel lang)
set(CMAKE_${lang}_CREATE_STATIC_LIBRARY_IPO
"${XIAR} cr <TARGET> <LINK_FLAGS> <OBJECTS> "
"${XIAR} -s <TARGET> ")
- set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
- set(_CMAKE_IPO_LEGACY_BEHAVIOR YES)
+ set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
+ set(_CMAKE_${lang}_IPO_LEGACY_BEHAVIOR YES)
else()
- set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
+ set(_CMAKE_${lang}_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
endif()
if(NOT CMAKE_${lang}_COMPILER_VERSION VERSION_LESS 12.0)
diff --git a/Modules/Platform/Windows-NVIDIA-CUDA.cmake b/Modules/Platform/Windows-NVIDIA-CUDA.cmake
index 845fa4b6ff..970c2c6d1f 100644
--- a/Modules/Platform/Windows-NVIDIA-CUDA.cmake
+++ b/Modules/Platform/Windows-NVIDIA-CUDA.cmake
@@ -30,10 +30,18 @@ set(CMAKE_CUDA_LINK_EXECUTABLE
unset(_CMAKE_VS_LINK_EXE)
unset(_CMAKE_VS_LINK_EXE)
+if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "8.0.0")
+ set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "-Wno-deprecated-gpu-targets")
+else()
+ set(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS "")
+endif()
+
set(CMAKE_CUDA_DEVICE_LINK_LIBRARY
- "<CMAKE_CUDA_COMPILER> <CMAKE_CUDA_LINK_FLAGS> <LANGUAGE_COMPILE_FLAGS> -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
+ "<CMAKE_CUDA_COMPILER> <CMAKE_CUDA_LINK_FLAGS> <LANGUAGE_COMPILE_FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
set(CMAKE_CUDA_DEVICE_LINK_EXECUTABLE
- "<CMAKE_CUDA_COMPILER> <FLAGS> <CMAKE_CUDA_LINK_FLAGS> -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
+ "<CMAKE_CUDA_COMPILER> <FLAGS> <CMAKE_CUDA_LINK_FLAGS> ${_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS} -shared -dlink <OBJECTS> -o <TARGET> <LINK_LIBRARIES> -Xcompiler=-Fd<TARGET_COMPILE_PDB>,-FS")
+
+unset(_CMAKE_CUDA_EXTRA_DEVICE_LINK_FLAGS)
string(REPLACE "/D" "-D" _PLATFORM_DEFINES_CUDA "${_PLATFORM_DEFINES}${_PLATFORM_DEFINES_CXX}")
diff --git a/README.rst b/README.rst
index 4188ea04c1..d5acd4a7c0 100644
--- a/README.rst
+++ b/README.rst
@@ -30,7 +30,13 @@ Building CMake
Supported Platforms
-------------------
-MS Windows, Mac OS X, Linux, FreeBSD, Solaris, HP-UX, IRIX, BeOS, QNX
+* Microsoft Windows
+* Apple macOS
+* Linux
+* FreeBSD
+* OpenBSD
+* Solaris
+* HP-UX
Other UNIX-like operating systems may work too out of the box, if not
it should not be a major problem to port CMake to this platform.
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 71650038a2..e458a96be0 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -2,4 +2,4 @@
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 9)
set(CMake_VERSION_PATCH 0)
-set(CMake_VERSION_RC 2)
+set(CMake_VERSION_RC 3)
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index c79e113ef2..b93442dc05 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -469,7 +469,8 @@ const char* cmGeneratorTarget::GetFeature(const std::string& feature,
return this->LocalGenerator->GetFeature(feature, config);
}
-bool cmGeneratorTarget::IsIPOEnabled(const std::string& config) const
+bool cmGeneratorTarget::IsIPOEnabled(std::string const& lang,
+ std::string const& config) const
{
const char* feature = "INTERPROCEDURAL_OPTIMIZATION";
const bool result = cmSystemTools::IsOn(this->GetFeature(feature, config));
@@ -479,10 +480,15 @@ bool cmGeneratorTarget::IsIPOEnabled(const std::string& config) const
return false;
}
+ if (lang != "C" && lang != "CXX" && lang != "Fortran") {
+ // We do not define IPO behavior for other languages.
+ return false;
+ }
+
cmPolicies::PolicyStatus cmp0069 = this->GetPolicyStatusCMP0069();
if (cmp0069 == cmPolicies::OLD || cmp0069 == cmPolicies::WARN) {
- if (this->Makefile->IsOn("_CMAKE_IPO_LEGACY_BEHAVIOR")) {
+ if (this->Makefile->IsOn("_CMAKE_" + lang + "_IPO_LEGACY_BEHAVIOR")) {
return true;
}
if (this->PolicyReportedCMP0069) {
@@ -506,10 +512,10 @@ bool cmGeneratorTarget::IsIPOEnabled(const std::string& config) const
// Note: check consistency with messages from CheckIPOSupported
const char* message = CM_NULLPTR;
- if (!this->Makefile->IsOn("_CMAKE_IPO_SUPPORTED_BY_CMAKE")) {
+ if (!this->Makefile->IsOn("_CMAKE_" + lang + "_IPO_SUPPORTED_BY_CMAKE")) {
message = "CMake doesn't support IPO for current compiler";
- } else if (!this->Makefile->IsOn(
- "_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER")) {
+ } else if (!this->Makefile->IsOn("_CMAKE_" + lang +
+ "_IPO_MAY_BE_SUPPORTED_BY_COMPILER")) {
message = "Compiler doesn't support IPO";
} else if (!this->GlobalGenerator->IsIPOSupported()) {
message = "CMake doesn't support IPO for current generator";
@@ -2417,9 +2423,10 @@ void cmGeneratorTarget::GetAppleArchs(const std::string& config,
//----------------------------------------------------------------------------
std::string cmGeneratorTarget::GetFeatureSpecificLinkRuleVariable(
- std::string const& var, std::string const& config) const
+ std::string const& var, std::string const& lang,
+ std::string const& config) const
{
- if (this->IsIPOEnabled(config)) {
+ if (this->IsIPOEnabled(lang, config)) {
std::string varIPO = var + "_IPO";
if (this->Makefile->IsDefinitionSet(varIPO)) {
return varIPO;
@@ -2436,7 +2443,7 @@ std::string cmGeneratorTarget::GetCreateRuleVariable(
switch (this->GetType()) {
case cmStateEnums::STATIC_LIBRARY: {
std::string var = "CMAKE_" + lang + "_CREATE_STATIC_LIBRARY";
- return this->GetFeatureSpecificLinkRuleVariable(var, config);
+ return this->GetFeatureSpecificLinkRuleVariable(var, lang, config);
}
case cmStateEnums::SHARED_LIBRARY:
return "CMAKE_" + lang + "_CREATE_SHARED_LIBRARY";
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 134b7c7b11..c04d62b547 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -165,7 +165,7 @@ public:
const char* GetFeature(const std::string& feature,
const std::string& config) const;
- bool IsIPOEnabled(const std::string& config) const;
+ bool IsIPOEnabled(std::string const& lang, std::string const& config) const;
bool IsLinkInterfaceDependentBoolProperty(const std::string& p,
const std::string& config) const;
@@ -385,7 +385,8 @@ public:
std::vector<std::string>& archVec) const;
std::string GetFeatureSpecificLinkRuleVariable(
- std::string const& var, std::string const& config) const;
+ std::string const& var, std::string const& lang,
+ std::string const& config) const;
/** Return the rule variable used to create this type of target. */
std::string GetCreateRuleVariable(std::string const& lang,
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 64616ad933..45c17648bc 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -1666,7 +1666,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt,
return;
}
- if (gtgt->IsIPOEnabled(configName)) {
+ if (gtgt->IsIPOEnabled(llang, configName)) {
const char* ltoValue =
this->CurrentMakefile->IsOn("_CMAKE_LTO_THIN") ? "YES_THIN" : "YES";
buildSettings->AddAttribute("LLVM_LTO", this->CreateString(ltoValue));
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index bc886b65c5..8e0030379f 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1334,7 +1334,7 @@ void cmLocalGenerator::AddLanguageFlags(std::string& flags,
flagsVar += "_FLAGS";
this->AddConfigVariableFlags(flags, flagsVar, config);
- if (target->IsIPOEnabled(config)) {
+ if (target->IsIPOEnabled(lang, config)) {
this->AppendFeatureOptions(flags, lang, "IPO");
}
}
@@ -1836,7 +1836,7 @@ void cmLocalGenerator::AppendIPOLinkerFlags(std::string& flags,
const std::string& config,
const std::string& lang)
{
- if (!target->IsIPOEnabled(config)) {
+ if (!target->IsIPOEnabled(lang, config)) {
return;
}
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index f86c0346d9..dd08e5bdb7 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -672,7 +672,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(
this->AddCompileOptions(flags, target, linkLanguage, configName);
// Check IPO related warning/error.
- target->IsIPOEnabled(configName);
+ target->IsIPOEnabled(linkLanguage, configName);
}
if (this->FortranProject) {
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 2b37b4dcaa..3d1594bdbf 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -699,7 +699,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
arCreateVar += "_ARCHIVE_CREATE";
arCreateVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
- arCreateVar, this->ConfigName);
+ arCreateVar, linkLanguage, this->ConfigName);
if (const char* rule = this->Makefile->GetDefinition(arCreateVar)) {
cmSystemTools::ExpandListArgument(rule, archiveCreateCommands);
@@ -709,7 +709,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
arAppendVar += "_ARCHIVE_APPEND";
arAppendVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
- arAppendVar, this->ConfigName);
+ arAppendVar, linkLanguage, this->ConfigName);
if (const char* rule = this->Makefile->GetDefinition(arAppendVar)) {
cmSystemTools::ExpandListArgument(rule, archiveAppendCommands);
@@ -719,7 +719,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules(
arFinishVar += "_ARCHIVE_FINISH";
arFinishVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
- arFinishVar, this->ConfigName);
+ arFinishVar, linkLanguage, this->ConfigName);
if (const char* rule = this->Makefile->GetDefinition(arFinishVar)) {
cmSystemTools::ExpandListArgument(rule, archiveFinishCommands);
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index 03318284fa..14a4ef8242 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -512,7 +512,7 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
linkCmdVar += "_ARCHIVE_CREATE";
linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
- linkCmdVar, this->GetConfigName());
+ linkCmdVar, this->TargetLinkLanguage, this->GetConfigName());
const char* linkCmd = mf->GetRequiredDefinition(linkCmdVar);
cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
@@ -523,7 +523,7 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd()
linkCmdVar += "_ARCHIVE_FINISH";
linkCmdVar = this->GeneratorTarget->GetFeatureSpecificLinkRuleVariable(
- linkCmdVar, this->GetConfigName());
+ linkCmdVar, this->TargetLinkLanguage, this->GetConfigName());
const char* linkCmd = mf->GetRequiredDefinition(linkCmdVar);
cmSystemTools::ExpandListArgument(linkCmd, linkCmds);
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 46c289476b..ca8a0995d1 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -2,6 +2,7 @@
file Copyright.txt or https://cmake.org/licensing for details. */
#include "cmVisualStudio10TargetGenerator.h"
+#include "cmAlgorithms.h"
#include "cmComputeLinkInformation.h"
#include "cmCustomCommandGenerator.h"
#include "cmGeneratedFileStream.h"
@@ -2227,10 +2228,27 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
this->Name.c_str());
return false;
}
- if (linkLanguage == "C" || linkLanguage == "CXX" ||
- linkLanguage == "Fortran" || linkLanguage == "CSharp") {
+
+ // Choose a language whose flags to use for ClCompile.
+ static const char* clLangs[] = { "CXX", "C", "Fortran", "CSharp" };
+ std::string langForClCompile;
+ if (std::find(cmArrayBegin(clLangs), cmArrayEnd(clLangs), linkLanguage) !=
+ cmArrayEnd(clLangs)) {
+ langForClCompile = linkLanguage;
+ } else {
+ std::set<std::string> languages;
+ this->GeneratorTarget->GetLanguages(languages, configName);
+ for (const char* const* l = cmArrayBegin(clLangs);
+ l != cmArrayEnd(clLangs); ++l) {
+ if (languages.find(*l) != languages.end()) {
+ langForClCompile = *l;
+ break;
+ }
+ }
+ }
+ if (!langForClCompile.empty()) {
std::string baseFlagVar = "CMAKE_";
- baseFlagVar += linkLanguage;
+ baseFlagVar += langForClCompile;
baseFlagVar += "_FLAGS";
flags =
this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
@@ -2241,6 +2259,8 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
flags +=
this->GeneratorTarget->Target->GetMakefile()->GetRequiredDefinition(
flagVar.c_str());
+ this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
+ langForClCompile, configName);
}
// set the correct language
if (linkLanguage == "C") {
@@ -2249,13 +2269,9 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
if (linkLanguage == "CXX") {
clOptions.AddFlag("CompileAs", "CompileAsCpp");
}
- if (linkLanguage != "CUDA") {
- this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget,
- linkLanguage, configName.c_str());
- }
// Check IPO related warning/error.
- this->GeneratorTarget->IsIPOEnabled(configName);
+ this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName);
// Get preprocessor definitions for this directory.
std::string defineFlags =
@@ -2480,6 +2496,8 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
std::string(this->Makefile->GetSafeDefinition("CMAKE_CUDA_FLAGS")) +
std::string(" ") +
std::string(this->Makefile->GetSafeDefinition(configFlagsVar));
+ this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, "CUDA",
+ configName);
// Get preprocessor definitions for this directory.
std::string defineFlags =
@@ -2505,9 +2523,16 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions(
cudaOptions.AddTable(gg->GetCudaHostFlagTable());
cudaOptions.Reparse("AdditionalCompilerOptions");
- // `CUDA 8.0.targets` places these before nvcc! Just drop whatever
- // did not parse and hope it works.
- cudaOptions.RemoveFlag("AdditionalCompilerOptions");
+ // `CUDA 8.0.targets` places AdditionalCompilerOptions before nvcc!
+ // Pass them through -Xcompiler in AdditionalOptions instead.
+ if (const char* acoPtr = cudaOptions.GetFlag("AdditionalCompilerOptions")) {
+ std::string aco = acoPtr;
+ cudaOptions.RemoveFlag("AdditionalCompilerOptions");
+ if (!aco.empty()) {
+ aco = this->LocalGenerator->EscapeForShell(aco, false);
+ cudaOptions.AppendFlag("AdditionalOptions", "-Xcompiler=" + aco);
+ }
+ }
cudaOptions.FixCudaCodeGeneration();
@@ -2591,6 +2616,13 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaLinkOptions(
cudaLinkOptions.AddFlag("PerformDeviceLink",
doDeviceLinking ? "true" : "false");
+ // Suppress deprecation warnings for default GPU targets during device link.
+ if (cmSystemTools::VersionCompareGreaterEq(
+ this->GlobalGenerator->GetPlatformToolsetCudaString(), "8.0")) {
+ cudaLinkOptions.AppendFlag("AdditionalOptions",
+ "-Wno-deprecated-gpu-targets");
+ }
+
this->CudaLinkOptions[configName] = pOptions.release();
return true;
}
@@ -3468,10 +3500,6 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences()
->TargetIsFortranOnly(dt)) {
continue;
}
- if (csproj == this->ProjectType &&
- !this->GlobalGenerator->TargetIsCSharpOnly(dt)) {
- continue;
- }
this->WriteString("<ProjectReference Include=\"", 2);
cmLocalGenerator* lg = dt->GetLocalGenerator();
std::string name = dt->GetName();
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index 6e65955077..c5a6836bf6 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -27,6 +27,10 @@
#include <vector>
#ifdef CMAKE_USE_LIBUV
+#ifdef _WIN32
+#include <fcntl.h> /* _O_TEXT */
+#include <stdlib.h> /* _set_fmode, _fmode */
+#endif
#include "cm_uv.h"
#endif
@@ -168,6 +172,18 @@ int main(int ac, char const* const* av)
ac = args.argc();
av = args.argv();
+#if defined(CMAKE_USE_LIBUV) && defined(_WIN32)
+ // Perform libuv one-time initialization now, and then un-do its
+ // global _fmode setting so that using libuv does not change the
+ // default file text/binary mode. See libuv issue 840.
+ uv_loop_close(uv_default_loop());
+#ifdef _MSC_VER
+ _set_fmode(_O_TEXT);
+#else
+ _fmode = _O_TEXT;
+#endif
+#endif
+
cmSystemTools::EnableMSVCDebugHook();
cmSystemTools::FindCMakeResources(av[0]);
if (ac > 1) {
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index d138f58681..d16df1cf5b 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -331,6 +331,7 @@ if(BUILD_TESTING)
if(${CMAKE_GENERATOR} MATCHES "Visual Studio ([^89]|[89][0-9])")
ADD_TEST_MACRO(CSharpOnly CSharpOnly)
+ ADD_TEST_MACRO(CSharpLinkToCxx CSharpLinkToCxx)
endif()
ADD_TEST_MACRO(COnly COnly)
diff --git a/Tests/CSharpLinkToCxx/CMakeLists.txt b/Tests/CSharpLinkToCxx/CMakeLists.txt
new file mode 100644
index 0000000000..c4269e0be7
--- /dev/null
+++ b/Tests/CSharpLinkToCxx/CMakeLists.txt
@@ -0,0 +1,17 @@
+# test if CSharp application correctly links
+# to managed C++ binary
+cmake_minimum_required(VERSION 3.9)
+project (CSharpLinkToCxx CXX CSharp)
+
+# we have to change the default flags for the
+# managed C++ project to build
+string(REPLACE "/EHsc" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
+string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
+
+add_library(CLIApp SHARED cli.hpp cli.cpp)
+
+target_compile_options(CLIApp PRIVATE "/clr")
+
+add_executable(CSharpLinkToCxx csharp.cs)
+
+target_link_libraries(CSharpLinkToCxx CLIApp)
diff --git a/Tests/CSharpLinkToCxx/cli.cpp b/Tests/CSharpLinkToCxx/cli.cpp
new file mode 100644
index 0000000000..97ac7246a2
--- /dev/null
+++ b/Tests/CSharpLinkToCxx/cli.cpp
@@ -0,0 +1,10 @@
+#include "cli.hpp"
+
+using namespace System;
+
+namespace CLIApp {
+void MyCli::testMyCli()
+{
+ Console::WriteLine("#message from CLIApp");
+}
+}
diff --git a/Tests/CSharpLinkToCxx/cli.hpp b/Tests/CSharpLinkToCxx/cli.hpp
new file mode 100644
index 0000000000..a8c116d4c4
--- /dev/null
+++ b/Tests/CSharpLinkToCxx/cli.hpp
@@ -0,0 +1,10 @@
+#pragma once
+
+namespace CLIApp {
+public
+ref class MyCli
+{
+public:
+ void testMyCli();
+};
+}
diff --git a/Tests/CSharpLinkToCxx/csharp.cs b/Tests/CSharpLinkToCxx/csharp.cs
new file mode 100644
index 0000000000..35c5cc3e8b
--- /dev/null
+++ b/Tests/CSharpLinkToCxx/csharp.cs
@@ -0,0 +1,16 @@
+using System;
+using CLIApp;
+
+namespace CSharpLinkToCxx
+{
+ internal class CSharpLinkToCxx
+ {
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("#message from CSharpLinkToCxx");
+
+ var app = new MyCli();
+ app.testMyCli();
+ }
+ }
+}
diff --git a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt
index 0a2542adf2..f42324ed12 100644
--- a/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt
+++ b/Tests/CudaOnly/SeparateCompilation/CMakeLists.txt
@@ -15,6 +15,10 @@ set(CMAKE_CUDA_STANDARD 11)
add_library(CUDASeparateLibA STATIC file1.cu file2.cu file3.cu)
+if(CMAKE_CUDA_SIMULATE_ID STREQUAL "MSVC")
+ target_compile_options(CUDASeparateLibA PRIVATE -Xcompiler=-bigobj)
+endif()
+
#Having file4/file5 in a shared library causes serious problems
#with the nvcc linker and it will generate bad entries that will
#cause a segv when trying to run the executable
diff --git a/Tests/CudaOnly/WithDefs/CMakeLists.txt b/Tests/CudaOnly/WithDefs/CMakeLists.txt
index 38f2a44a34..e25f141ea5 100644
--- a/Tests/CudaOnly/WithDefs/CMakeLists.txt
+++ b/Tests/CudaOnly/WithDefs/CMakeLists.txt
@@ -28,6 +28,7 @@ add_executable(CudaOnlyWithDefs ${main})
target_compile_options(CudaOnlyWithDefs
PRIVATE
+ -Xcompiler=-DHOST_DEFINE
$<$<CONFIG:DEBUG>:$<BUILD_INTERFACE:${debug_compile_flags}>>
)
diff --git a/Tests/CudaOnly/WithDefs/main.notcu b/Tests/CudaOnly/WithDefs/main.notcu
index 80ed3a5050..d2eff3f4b3 100644
--- a/Tests/CudaOnly/WithDefs/main.notcu
+++ b/Tests/CudaOnly/WithDefs/main.notcu
@@ -2,6 +2,10 @@
#include <cuda_runtime.h>
#include <iostream>
+#ifndef HOST_DEFINE
+#error "HOST_DEFINE not defined!"
+#endif
+
#ifndef PACKED_DEFINE
#error "PACKED_DEFINE not defined!"
#endif
diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake.cmake b/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake.cmake
index 23fae13a34..6968c8bbf2 100644
--- a/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake.cmake
+++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-cmake.cmake
@@ -1,6 +1,6 @@
cmake_policy(SET CMP0069 NEW)
-set(_CMAKE_IPO_SUPPORTED_BY_CMAKE NO)
+set(_CMAKE_CXX_IPO_SUPPORTED_BY_CMAKE NO)
add_executable(foo main.cpp)
set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler.cmake b/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler.cmake
index 24b409acdc..ecb197b393 100644
--- a/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler.cmake
+++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-compiler.cmake
@@ -1,7 +1,7 @@
cmake_policy(SET CMP0069 NEW)
-set(_CMAKE_IPO_SUPPORTED_BY_CMAKE YES)
-set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
+set(_CMAKE_CXX_IPO_SUPPORTED_BY_CMAKE YES)
+set(_CMAKE_CXX_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
add_executable(foo main.cpp)
set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
diff --git a/Tests/RunCMake/CMP0069/CMP0069-NEW-generator.cmake b/Tests/RunCMake/CMP0069/CMP0069-NEW-generator.cmake
index df2a888c08..80d4e15441 100644
--- a/Tests/RunCMake/CMP0069/CMP0069-NEW-generator.cmake
+++ b/Tests/RunCMake/CMP0069/CMP0069-NEW-generator.cmake
@@ -1,7 +1,7 @@
cmake_policy(SET CMP0069 NEW)
-set(_CMAKE_IPO_SUPPORTED_BY_CMAKE YES)
-set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
+set(_CMAKE_CXX_IPO_SUPPORTED_BY_CMAKE YES)
+set(_CMAKE_CXX_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
add_executable(foo main.cpp)
set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
diff --git a/Tests/RunCMake/CMP0069/CMP0069-WARN.cmake b/Tests/RunCMake/CMP0069/CMP0069-WARN.cmake
index 0e3e6705a3..2049c9e75b 100644
--- a/Tests/RunCMake/CMP0069/CMP0069-WARN.cmake
+++ b/Tests/RunCMake/CMP0069/CMP0069-WARN.cmake
@@ -1,4 +1,4 @@
-set(_CMAKE_IPO_LEGACY_BEHAVIOR NO)
+set(_CMAKE_CXX_IPO_LEGACY_BEHAVIOR NO)
add_executable(foo main.cpp)
set_target_properties(foo PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake-stderr.txt b/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake-stderr.txt
index f63f30f9fa..c49a02439d 100644
--- a/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake-stderr.txt
+++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake-stderr.txt
@@ -1,5 +1,5 @@
^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\):
- IPO is not supported \(CMake doesn't support IPO for current compiler\)\.
+ IPO is not supported \(CMake doesn't support IPO for current C compiler\)\.
Call Stack \(most recent call first\):
.*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(_ipo_not_supported\)
not-supported-by-cmake\.cmake:[0-9]+ \(check_ipo_supported\)
diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake.cmake b/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake.cmake
index 6f61f7e34a..e583dd02c3 100644
--- a/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake.cmake
+++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-cmake.cmake
@@ -1,3 +1,3 @@
project(${RunCMake_TEST} LANGUAGES C)
-set(_CMAKE_IPO_SUPPORTED_BY_CMAKE NO)
+set(_CMAKE_C_IPO_SUPPORTED_BY_CMAKE NO)
check_ipo_supported()
diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-stderr.txt b/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-stderr.txt
index 5f5f41051b..675c2d393c 100644
--- a/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-stderr.txt
+++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler-stderr.txt
@@ -1,5 +1,5 @@
^CMake Error at .*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(message\):
- IPO is not supported \(Compiler doesn't support IPO\)\.
+ IPO is not supported \(C compiler doesn't support IPO\)\.
Call Stack \(most recent call first\):
.*/Modules/CheckIPOSupported\.cmake:[0-9]+ \(_ipo_not_supported\)
not-supported-by-compiler\.cmake:[0-9]+ \(check_ipo_supported\)
diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler.cmake b/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler.cmake
index 652cfd5b2b..86c8f8d43c 100644
--- a/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler.cmake
+++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-compiler.cmake
@@ -1,4 +1,4 @@
project(${RunCMake_TEST} LANGUAGES C)
-set(_CMAKE_IPO_SUPPORTED_BY_CMAKE YES)
-set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
+set(_CMAKE_C_IPO_SUPPORTED_BY_CMAKE YES)
+set(_CMAKE_C_IPO_MAY_BE_SUPPORTED_BY_COMPILER NO)
check_ipo_supported()
diff --git a/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator.cmake b/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator.cmake
index dc0fa09674..c32af6ed3b 100644
--- a/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator.cmake
+++ b/Tests/RunCMake/CheckIPOSupported/not-supported-by-generator.cmake
@@ -1,6 +1,6 @@
project(${RunCMake_TEST} LANGUAGES C)
-set(_CMAKE_IPO_SUPPORTED_BY_CMAKE YES)
-set(_CMAKE_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
+set(_CMAKE_C_IPO_SUPPORTED_BY_CMAKE YES)
+set(_CMAKE_C_IPO_MAY_BE_SUPPORTED_BY_COMPILER YES)
check_ipo_supported()
diff --git a/Utilities/Scripts/update-curl.bash b/Utilities/Scripts/update-curl.bash
index d270d377fe..465841a02d 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_54_0"
+readonly tag="curl-7_54_1"
readonly shortlog=false
readonly paths="
CMake/*
diff --git a/Utilities/Scripts/update-expat.bash b/Utilities/Scripts/update-expat.bash
index 8a2a5fe4f8..4cc8646099 100755
--- a/Utilities/Scripts/update-expat.bash
+++ b/Utilities/Scripts/update-expat.bash
@@ -7,8 +7,8 @@ shopt -s dotglob
readonly name="expat"
readonly ownership="Expat Upstream <kwrobot@kitware.com>"
readonly subtree="Utilities/cmexpat"
-readonly repo="http://git.code.sf.net/p/expat/code_git"
-readonly tag="master"
+readonly repo="https://github.com/libexpat/libexpat.git"
+readonly tag="R_2_2_1"
readonly shortlog=false
readonly paths="
expat/lib/asciitab.h
@@ -22,6 +22,7 @@ readonly paths="
expat/lib/utf8tab.h
expat/lib/nametab.h
expat/lib/ascii.h
+ expat/lib/siphash.h
expat/lib/xmltok_impl.h
expat/lib/xmltok_ns.c
expat/lib/winconfig.h
diff --git a/Utilities/cmcurl/CMakeLists.txt b/Utilities/cmcurl/CMakeLists.txt
index 5049d7b64b..45ae3de027 100644
--- a/Utilities/cmcurl/CMakeLists.txt
+++ b/Utilities/cmcurl/CMakeLists.txt
@@ -487,7 +487,7 @@ if(CMAKE_USE_MBEDTLS)
set(SSL_ENABLED ON)
set(USE_MBEDTLS ON)
list(APPEND CURL_LIBS ${MBEDTLS_LIBRARIES})
- include_directories(${MBEDTLS_INCLUDE_DIR})
+ include_directories(${MBEDTLS_INCLUDE_DIRS})
endif()
option(USE_NGHTTP2 "Use Nghttp2 library" OFF)
@@ -742,6 +742,80 @@ else()
endif()
+if(0) # This code not needed for building within CMake.
+#
+# CA handling
+#
+set(CURL_CA_BUNDLE "auto" CACHE STRING
+ "Path to the CA bundle. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
+set(CURL_CA_FALLBACK OFF CACHE BOOL
+ "Set ON to use built-in CA store of TLS backend. Defaults to OFF")
+set(CURL_CA_PATH "auto" CACHE STRING
+ "Location of default CA path. Set 'none' to disable or 'auto' for auto-detection. Defaults to 'auto'.")
+
+if("${CURL_CA_BUNDLE}" STREQUAL "")
+ message(FATAL_ERROR "Invalid value of CURL_CA_BUNDLE. Use 'none', 'auto' or file path.")
+elseif("${CURL_CA_BUNDLE}" STREQUAL "none")
+ unset(CURL_CA_BUNDLE CACHE)
+elseif("${CURL_CA_BUNDLE}" STREQUAL "auto")
+ unset(CURL_CA_BUNDLE CACHE)
+ set(CURL_CA_BUNDLE_AUTODETECT TRUE)
+else()
+ set(CURL_CA_BUNDLE_SET TRUE)
+endif()
+
+if("${CURL_CA_PATH}" STREQUAL "")
+ message(FATAL_ERROR "Invalid value of CURL_CA_PATH. Use 'none', 'auto' or directory path.")
+elseif("${CURL_CA_PATH}" STREQUAL "none")
+ unset(CURL_CA_PATH CACHE)
+elseif("${CURL_CA_PATH}" STREQUAL "auto")
+ unset(CURL_CA_PATH CACHE)
+ set(CURL_CA_PATH_AUTODETECT TRUE)
+else()
+ set(CURL_CA_PATH_SET TRUE)
+endif()
+
+if(CURL_CA_BUNDLE_SET AND CURL_CA_PATH_AUTODETECT)
+ # Skip autodetection of unset CA path because CA bundle is set explicitly
+elseif(CURL_CA_PATH_SET AND CURL_CA_BUNDLE_AUTODETECT)
+ # Skip autodetection of unset CA bundle because CA path is set explicitly
+elseif(CURL_CA_PATH_AUTODETECT OR CURL_CA_BUNDLE_AUTODETECT)
+ # first try autodetecting a CA bundle, then a CA path
+
+ if(CURL_CA_BUNDLE_AUTODETECT)
+ set(SEARCH_CA_BUNDLE_PATHS
+ /etc/ssl/certs/ca-certificates.crt
+ /etc/pki/tls/certs/ca-bundle.crt
+ /usr/share/ssl/certs/ca-bundle.crt
+ /usr/local/share/certs/ca-root-nss.crt
+ /etc/ssl/cert.pem)
+
+ foreach(SEARCH_CA_BUNDLE_PATH ${SEARCH_CA_BUNDLE_PATHS})
+ if(EXISTS "${SEARCH_CA_BUNDLE_PATH}")
+ message(STATUS "Found CA bundle: ${SEARCH_CA_BUNDLE_PATH}")
+ set(CURL_CA_BUNDLE "${SEARCH_CA_BUNDLE_PATH}")
+ set(CURL_CA_BUNDLE_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
+ break()
+ endif()
+ endforeach()
+ endif()
+
+ if(CURL_CA_PATH_AUTODETECT AND (NOT CURL_CA_PATH_SET))
+ if(EXISTS "/etc/ssl/certs")
+ set(CURL_CA_PATH "/etc/ssl/certs")
+ set(CURL_CA_PATH_SET TRUE CACHE BOOL "Path to the CA bundle has been set")
+ endif()
+ endif()
+endif()
+
+if(CURL_CA_PATH_SET AND NOT USE_OPENSSL AND NOT USE_MBEDTLS)
+ message(FATAL_ERROR
+ "CA path only supported by OpenSSL, GnuTLS or mbed TLS. "
+ "Set CURL_CA_PATH=none or enable one of those TLS backends.")
+endif()
+endif()
+
+
# Check for header files
if(NOT UNIX)
check_include_file_concat("windows.h" HAVE_WINDOWS_H)
@@ -1217,8 +1291,7 @@ _add_if("Kerberos" NOT CURL_DISABLE_CRYPTO_AUTH AND
(HAVE_GSSAPI OR USE_WINDOWS_SSPI))
# NTLM support requires crypto function adaptions from various SSL libs
# TODO alternative SSL libs tests for SSP1, GNUTLS, NSS
-if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR
- USE_WINDOWS_SSPI OR GNUTLS_ENABLED OR NSS_ENABLED OR USE_DARWINSSL OR USE_MBEDTLS))
+if(NOT CURL_DISABLE_CRYPTO_AUTH AND (USE_OPENSSL OR USE_WINDOWS_SSPI OR USE_DARWINSSL OR USE_MBEDTLS))
_add_if("NTLM" 1)
# TODO missing option (autoconf: --enable-ntlm-wb)
_add_if("NTLM_WB" NOT CURL_DISABLE_HTTP AND NTLM_WB_ENABLED)
@@ -1267,8 +1340,6 @@ set(CC "${CMAKE_C_COMPILER}")
set(CONFIGURE_OPTIONS "")
# TODO when to set "-DCURL_STATICLIB" for CPPFLAG_CURL_STATICLIB?
set(CPPFLAG_CURL_STATICLIB "")
-# TODO need to set this (see CURL_CHECK_CA_BUNDLE in acinclude.m4)
-set(CURL_CA_BUNDLE "")
set(CURLVERSION "${CURL_VERSION}")
set(ENABLE_SHARED "yes")
if(CURL_STATICLIB)
diff --git a/Utilities/cmcurl/include/curl/curl.h b/Utilities/cmcurl/include/curl/curl.h
index b19dd4299c..395521202f 100644
--- a/Utilities/cmcurl/include/curl/curl.h
+++ b/Utilities/cmcurl/include/curl/curl.h
@@ -2251,6 +2251,7 @@ struct curl_tlssessioninfo {
#define CURLINFO_LONG 0x200000
#define CURLINFO_DOUBLE 0x300000
#define CURLINFO_SLIST 0x400000
+#define CURLINFO_PTR 0x400000 /* same as SLIST */
#define CURLINFO_SOCKET 0x500000
#define CURLINFO_MASK 0x0fffff
#define CURLINFO_TYPEMASK 0xf00000
@@ -2290,7 +2291,7 @@ typedef enum {
CURLINFO_REDIRECT_URL = CURLINFO_STRING + 31,
CURLINFO_PRIMARY_IP = CURLINFO_STRING + 32,
CURLINFO_APPCONNECT_TIME = CURLINFO_DOUBLE + 33,
- CURLINFO_CERTINFO = CURLINFO_SLIST + 34,
+ CURLINFO_CERTINFO = CURLINFO_PTR + 34,
CURLINFO_CONDITION_UNMET = CURLINFO_LONG + 35,
CURLINFO_RTSP_SESSION_ID = CURLINFO_STRING + 36,
CURLINFO_RTSP_CLIENT_CSEQ = CURLINFO_LONG + 37,
@@ -2299,9 +2300,9 @@ typedef enum {
CURLINFO_PRIMARY_PORT = CURLINFO_LONG + 40,
CURLINFO_LOCAL_IP = CURLINFO_STRING + 41,
CURLINFO_LOCAL_PORT = CURLINFO_LONG + 42,
- CURLINFO_TLS_SESSION = CURLINFO_SLIST + 43,
+ CURLINFO_TLS_SESSION = CURLINFO_PTR + 43,
CURLINFO_ACTIVESOCKET = CURLINFO_SOCKET + 44,
- CURLINFO_TLS_SSL_PTR = CURLINFO_SLIST + 45,
+ CURLINFO_TLS_SSL_PTR = CURLINFO_PTR + 45,
CURLINFO_HTTP_VERSION = CURLINFO_LONG + 46,
CURLINFO_PROXY_SSL_VERIFYRESULT = CURLINFO_LONG + 47,
CURLINFO_PROTOCOL = CURLINFO_LONG + 48,
diff --git a/Utilities/cmcurl/include/curl/curlver.h b/Utilities/cmcurl/include/curl/curlver.h
index 7f0e3b8cf6..667b7eb133 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.54.0"
+#define LIBCURL_VERSION "7.54.1"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 54
-#define LIBCURL_VERSION_PATCH 0
+#define LIBCURL_VERSION_PATCH 1
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
@@ -57,18 +57,18 @@
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 0x073600
+#define LIBCURL_VERSION_NUM 0x073601
/*
* This is the date and time when the full source package was created. The
* timestamp is not stored in git, as the timestamp is properly set in the
* tarballs by the maketgz script.
*
- * The format of the date should follow this template:
+ * The format of the date follows this template:
*
- * "Mon Feb 12 11:35:33 UTC 2007"
+ * "2007-11-23"
*/
-#define LIBCURL_TIMESTAMP "DEV"
+#define LIBCURL_TIMESTAMP "[unreleased]"
#define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|z)
#define CURL_AT_LEAST_VERSION(x,y,z) \
diff --git a/Utilities/cmcurl/include/curl/typecheck-gcc.h b/Utilities/cmcurl/include/curl/typecheck-gcc.h
index 3d683152b6..10b5de2ab1 100644
--- a/Utilities/cmcurl/include/curl/typecheck-gcc.h
+++ b/Utilities/cmcurl/include/curl/typecheck-gcc.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -124,6 +124,15 @@ __extension__ ({ \
if(_curl_is_slist_info(_curl_info)) \
if(!_curl_is_arr((arg), struct curl_slist *)) \
_curl_easy_getinfo_err_curl_slist(); \
+ if(_curl_is_tlssessioninfo_info(_curl_info)) \
+ if(!_curl_is_arr((arg), struct curl_tlssessioninfo *)) \
+ _curl_easy_getinfo_err_curl_tlssesssioninfo(); \
+ if(_curl_is_certinfo_info(_curl_info)) \
+ if(!_curl_is_arr((arg), struct curl_certinfo *)) \
+ _curl_easy_getinfo_err_curl_certinfo(); \
+ if(_curl_is_socket_info(_curl_info)) \
+ if(!_curl_is_arr((arg), curl_socket_t)) \
+ _curl_easy_getinfo_err_curl_socket(); \
} \
curl_easy_getinfo(handle, _curl_info, arg); \
})
@@ -201,6 +210,14 @@ _CURL_WARNING(_curl_easy_getinfo_err_double,
"curl_easy_getinfo expects a pointer to double for this info")
_CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
"curl_easy_getinfo expects a pointer to 'struct curl_slist *' for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_curl_tlssesssioninfo,
+ "curl_easy_getinfo expects a pointer to "
+ "'struct curl_tlssessioninfo *' for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_curl_certinfo,
+ "curl_easy_getinfo expects a pointer to "
+ "'struct curl_certinfo *' for this info")
+_CURL_WARNING(_curl_easy_getinfo_err_curl_socket,
+ "curl_easy_getinfo expects a pointer to curl_socket_t for this info")
/* groups of curl_easy_setops options that take the same type of argument */
@@ -249,11 +266,25 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
(option) == CURLOPT_NOPROXY || \
(option) == CURLOPT_PASSWORD || \
(option) == CURLOPT_PINNEDPUBLICKEY || \
+ (option) == CURLOPT_PRE_PROXY || \
(option) == CURLOPT_PROXY || \
(option) == CURLOPT_PROXYPASSWORD || \
(option) == CURLOPT_PROXYUSERNAME || \
(option) == CURLOPT_PROXYUSERPWD || \
+ (option) == CURLOPT_PROXY_CAINFO || \
+ (option) == CURLOPT_PROXY_CAPATH || \
+ (option) == CURLOPT_PROXY_CRLFILE || \
+ (option) == CURLOPT_PROXY_KEYPASSWD || \
+ (option) == CURLOPT_PROXY_PINNEDPUBLICKEY || \
(option) == CURLOPT_PROXY_SERVICE_NAME || \
+ (option) == CURLOPT_PROXY_SSLCERT || \
+ (option) == CURLOPT_PROXY_SSLCERTTYPE || \
+ (option) == CURLOPT_PROXY_SSLKEY || \
+ (option) == CURLOPT_PROXY_SSLKEYTYPE || \
+ (option) == CURLOPT_PROXY_SSL_CIPHER_LIST || \
+ (option) == CURLOPT_PROXY_TLSAUTH_PASSWORD || \
+ (option) == CURLOPT_PROXY_TLSAUTH_USERNAME || \
+ (option) == CURLOPT_PROXY_TLSAUTH_TYPE || \
(option) == CURLOPT_RANDOM_FILE || \
(option) == CURLOPT_RANGE || \
(option) == CURLOPT_REFERER || \
@@ -348,8 +379,19 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
(CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
/* true if info expects a pointer to struct curl_slist * argument */
-#define _curl_is_slist_info(info) \
- (CURLINFO_SLIST < (info))
+#define _curl_is_slist_info(info) \
+ (((info) == CURLINFO_SSL_ENGINES) || ((info) == CURLINFO_COOKIELIST))
+
+/* true if info expects a pointer to struct curl_tlssessioninfo * argument */
+#define _curl_is_tlssessioninfo_info(info) \
+ (((info) == CURLINFO_TLS_SSL_PTR) || ((info) == CURLINFO_TLS_SESSION))
+
+/* true if info expects a pointer to struct curl_certinfo * argument */
+#define _curl_is_certinfo_info(info) ((info) == CURLINFO_CERTINFO)
+
+/* true if info expects a pointer to struct curl_socket_t argument */
+#define _curl_is_socket_info(info) \
+ (CURLINFO_SOCKET < (info))
/* typecheck helpers -- check whether given expression has requested type*/
@@ -428,8 +470,9 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
#endif
/* evaluates to true if expr is of type FILE* */
-#define _curl_is_FILE(expr) \
- (__builtin_types_compatible_p(__typeof__(expr), FILE *))
+#define _curl_is_FILE(expr) \
+ (_curl_is_NULL(expr) || \
+ (__builtin_types_compatible_p(__typeof__(expr), FILE *)))
/* evaluates to true if expr can be passed as POST data (void* or char*) */
#define _curl_is_postfields(expr) \
@@ -444,102 +487,102 @@ _CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
* function pointers, hide it */
#define _curl_callback_compatible(func, type) \
(__builtin_types_compatible_p(__typeof__(func), type) || \
- __builtin_types_compatible_p(__typeof__(func), type*))
+ __builtin_types_compatible_p(__typeof__(func) *, type))
/* evaluates to true if expr is of type curl_read_callback or "similar" */
#define _curl_is_read_cb(expr) \
(_curl_is_NULL(expr) || \
- __builtin_types_compatible_p(__typeof__(expr), __typeof__(fread)) || \
- __builtin_types_compatible_p(__typeof__(expr), curl_read_callback) || \
+ _curl_callback_compatible((expr), __typeof__(fread) *) || \
+ _curl_callback_compatible((expr), curl_read_callback) || \
_curl_callback_compatible((expr), _curl_read_callback1) || \
_curl_callback_compatible((expr), _curl_read_callback2) || \
_curl_callback_compatible((expr), _curl_read_callback3) || \
_curl_callback_compatible((expr), _curl_read_callback4) || \
_curl_callback_compatible((expr), _curl_read_callback5) || \
_curl_callback_compatible((expr), _curl_read_callback6))
-typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void *);
-typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void *);
-typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE *);
-typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void *);
-typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void *);
-typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE *);
+typedef size_t (*_curl_read_callback1)(char *, size_t, size_t, void *);
+typedef size_t (*_curl_read_callback2)(char *, size_t, size_t, const void *);
+typedef size_t (*_curl_read_callback3)(char *, size_t, size_t, FILE *);
+typedef size_t (*_curl_read_callback4)(void *, size_t, size_t, void *);
+typedef size_t (*_curl_read_callback5)(void *, size_t, size_t, const void *);
+typedef size_t (*_curl_read_callback6)(void *, size_t, size_t, FILE *);
/* evaluates to true if expr is of type curl_write_callback or "similar" */
#define _curl_is_write_cb(expr) \
(_curl_is_read_cb(expr) || \
- __builtin_types_compatible_p(__typeof__(expr), __typeof__(fwrite)) || \
- __builtin_types_compatible_p(__typeof__(expr), curl_write_callback) || \
+ _curl_callback_compatible((expr), __typeof__(fwrite) *) || \
+ _curl_callback_compatible((expr), curl_write_callback) || \
_curl_callback_compatible((expr), _curl_write_callback1) || \
_curl_callback_compatible((expr), _curl_write_callback2) || \
_curl_callback_compatible((expr), _curl_write_callback3) || \
_curl_callback_compatible((expr), _curl_write_callback4) || \
_curl_callback_compatible((expr), _curl_write_callback5) || \
_curl_callback_compatible((expr), _curl_write_callback6))
-typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void *);
-typedef size_t (_curl_write_callback2)(const char *, size_t, size_t,
+typedef size_t (*_curl_write_callback1)(const char *, size_t, size_t, void *);
+typedef size_t (*_curl_write_callback2)(const char *, size_t, size_t,
const void *);
-typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE *);
-typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void *);
-typedef size_t (_curl_write_callback5)(const void *, size_t, size_t,
+typedef size_t (*_curl_write_callback3)(const char *, size_t, size_t, FILE *);
+typedef size_t (*_curl_write_callback4)(const void *, size_t, size_t, void *);
+typedef size_t (*_curl_write_callback5)(const void *, size_t, size_t,
const void *);
-typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE *);
+typedef size_t (*_curl_write_callback6)(const void *, size_t, size_t, FILE *);
/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
#define _curl_is_ioctl_cb(expr) \
(_curl_is_NULL(expr) || \
- __builtin_types_compatible_p(__typeof__(expr), curl_ioctl_callback) || \
+ _curl_callback_compatible((expr), curl_ioctl_callback) || \
_curl_callback_compatible((expr), _curl_ioctl_callback1) || \
_curl_callback_compatible((expr), _curl_ioctl_callback2) || \
_curl_callback_compatible((expr), _curl_ioctl_callback3) || \
_curl_callback_compatible((expr), _curl_ioctl_callback4))
-typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void *);
-typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void *);
-typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void *);
-typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void *);
+typedef curlioerr (*_curl_ioctl_callback1)(CURL *, int, void *);
+typedef curlioerr (*_curl_ioctl_callback2)(CURL *, int, const void *);
+typedef curlioerr (*_curl_ioctl_callback3)(CURL *, curliocmd, void *);
+typedef curlioerr (*_curl_ioctl_callback4)(CURL *, curliocmd, const void *);
/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
#define _curl_is_sockopt_cb(expr) \
(_curl_is_NULL(expr) || \
- __builtin_types_compatible_p(__typeof__(expr), curl_sockopt_callback) || \
+ _curl_callback_compatible((expr), curl_sockopt_callback) || \
_curl_callback_compatible((expr), _curl_sockopt_callback1) || \
_curl_callback_compatible((expr), _curl_sockopt_callback2))
-typedef int (_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
-typedef int (_curl_sockopt_callback2)(const void *, curl_socket_t,
+typedef int (*_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
+typedef int (*_curl_sockopt_callback2)(const void *, curl_socket_t,
curlsocktype);
/* evaluates to true if expr is of type curl_opensocket_callback or
"similar" */
#define _curl_is_opensocket_cb(expr) \
(_curl_is_NULL(expr) || \
- __builtin_types_compatible_p(__typeof__(expr), curl_opensocket_callback) ||\
+ _curl_callback_compatible((expr), curl_opensocket_callback) || \
_curl_callback_compatible((expr), _curl_opensocket_callback1) || \
_curl_callback_compatible((expr), _curl_opensocket_callback2) || \
_curl_callback_compatible((expr), _curl_opensocket_callback3) || \
_curl_callback_compatible((expr), _curl_opensocket_callback4))
-typedef curl_socket_t (_curl_opensocket_callback1)
+typedef curl_socket_t (*_curl_opensocket_callback1)
(void *, curlsocktype, struct curl_sockaddr *);
-typedef curl_socket_t (_curl_opensocket_callback2)
+typedef curl_socket_t (*_curl_opensocket_callback2)
(void *, curlsocktype, const struct curl_sockaddr *);
-typedef curl_socket_t (_curl_opensocket_callback3)
+typedef curl_socket_t (*_curl_opensocket_callback3)
(const void *, curlsocktype, struct curl_sockaddr *);
-typedef curl_socket_t (_curl_opensocket_callback4)
+typedef curl_socket_t (*_curl_opensocket_callback4)
(const void *, curlsocktype, const struct curl_sockaddr *);
/* evaluates to true if expr is of type curl_progress_callback or "similar" */
#define _curl_is_progress_cb(expr) \
(_curl_is_NULL(expr) || \
- __builtin_types_compatible_p(__typeof__(expr), curl_progress_callback) || \
+ _curl_callback_compatible((expr), curl_progress_callback) || \
_curl_callback_compatible((expr), _curl_progress_callback1) || \
_curl_callback_compatible((expr), _curl_progress_callback2))
-typedef int (_curl_progress_callback1)(void *,
+typedef int (*_curl_progress_callback1)(void *,
double, double, double, double);
-typedef int (_curl_progress_callback2)(const void *,
+typedef int (*_curl_progress_callback2)(const void *,
double, double, double, double);
/* evaluates to true if expr is of type curl_debug_callback or "similar" */
#define _curl_is_debug_cb(expr) \
(_curl_is_NULL(expr) || \
- __builtin_types_compatible_p(__typeof__(expr), curl_debug_callback) || \
+ _curl_callback_compatible((expr), curl_debug_callback) || \
_curl_callback_compatible((expr), _curl_debug_callback1) || \
_curl_callback_compatible((expr), _curl_debug_callback2) || \
_curl_callback_compatible((expr), _curl_debug_callback3) || \
@@ -548,28 +591,28 @@ typedef int (_curl_progress_callback2)(const void *,
_curl_callback_compatible((expr), _curl_debug_callback6) || \
_curl_callback_compatible((expr), _curl_debug_callback7) || \
_curl_callback_compatible((expr), _curl_debug_callback8))
-typedef int (_curl_debug_callback1) (CURL *,
+typedef int (*_curl_debug_callback1) (CURL *,
curl_infotype, char *, size_t, void *);
-typedef int (_curl_debug_callback2) (CURL *,
+typedef int (*_curl_debug_callback2) (CURL *,
curl_infotype, char *, size_t, const void *);
-typedef int (_curl_debug_callback3) (CURL *,
+typedef int (*_curl_debug_callback3) (CURL *,
curl_infotype, const char *, size_t, void *);
-typedef int (_curl_debug_callback4) (CURL *,
+typedef int (*_curl_debug_callback4) (CURL *,
curl_infotype, const char *, size_t, const void *);
-typedef int (_curl_debug_callback5) (CURL *,
+typedef int (*_curl_debug_callback5) (CURL *,
curl_infotype, unsigned char *, size_t, void *);
-typedef int (_curl_debug_callback6) (CURL *,
+typedef int (*_curl_debug_callback6) (CURL *,
curl_infotype, unsigned char *, size_t, const void *);
-typedef int (_curl_debug_callback7) (CURL *,
+typedef int (*_curl_debug_callback7) (CURL *,
curl_infotype, const unsigned char *, size_t, void *);
-typedef int (_curl_debug_callback8) (CURL *,
+typedef int (*_curl_debug_callback8) (CURL *,
curl_infotype, const unsigned char *, size_t, const void *);
/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
/* this is getting even messier... */
#define _curl_is_ssl_ctx_cb(expr) \
(_curl_is_NULL(expr) || \
- __builtin_types_compatible_p(__typeof__(expr), curl_ssl_ctx_callback) || \
+ _curl_callback_compatible((expr), curl_ssl_ctx_callback) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback1) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback2) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback3) || \
@@ -578,18 +621,19 @@ typedef int (_curl_debug_callback8) (CURL *,
_curl_callback_compatible((expr), _curl_ssl_ctx_callback6) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback7) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback8))
-typedef CURLcode (_curl_ssl_ctx_callback1)(CURL *, void *, void *);
-typedef CURLcode (_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
-typedef CURLcode (_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
-typedef CURLcode (_curl_ssl_ctx_callback4)(CURL *, const void *, const void *);
+typedef CURLcode (*_curl_ssl_ctx_callback1)(CURL *, void *, void *);
+typedef CURLcode (*_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
+typedef CURLcode (*_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
+typedef CURLcode (*_curl_ssl_ctx_callback4)(CURL *, const void *,
+ const void *);
#ifdef HEADER_SSL_H
/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX
* this will of course break if we're included before OpenSSL headers...
*/
-typedef CURLcode (_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *);
-typedef CURLcode (_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *);
-typedef CURLcode (_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *);
-typedef CURLcode (_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX,
+typedef CURLcode (*_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *);
+typedef CURLcode (*_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *);
+typedef CURLcode (*_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *);
+typedef CURLcode (*_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX,
const void *);
#else
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5;
@@ -601,7 +645,7 @@ typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
/* evaluates to true if expr is of type curl_conv_callback or "similar" */
#define _curl_is_conv_cb(expr) \
(_curl_is_NULL(expr) || \
- __builtin_types_compatible_p(__typeof__(expr), curl_conv_callback) || \
+ _curl_callback_compatible((expr), curl_conv_callback) || \
_curl_callback_compatible((expr), _curl_conv_callback1) || \
_curl_callback_compatible((expr), _curl_conv_callback2) || \
_curl_callback_compatible((expr), _curl_conv_callback3) || \
@@ -614,7 +658,7 @@ typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length);
/* evaluates to true if expr is of type curl_seek_callback or "similar" */
#define _curl_is_seek_cb(expr) \
(_curl_is_NULL(expr) || \
- __builtin_types_compatible_p(__typeof__(expr), curl_seek_callback) || \
+ _curl_callback_compatible((expr), curl_seek_callback) || \
_curl_callback_compatible((expr), _curl_seek_callback1) || \
_curl_callback_compatible((expr), _curl_seek_callback2))
typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
diff --git a/Utilities/cmcurl/lib/asyn-ares.c b/Utilities/cmcurl/lib/asyn-ares.c
index 281fb03c8b..11a914f824 100644
--- a/Utilities/cmcurl/lib/asyn-ares.c
+++ b/Utilities/cmcurl/lib/asyn-ares.c
@@ -232,7 +232,7 @@ int Curl_resolver_getsock(struct connectdata *conn,
milli = (timeout->tv_sec * 1000) + (timeout->tv_usec/1000);
if(milli == 0)
milli += 10;
- Curl_expire_latest(conn->data, milli);
+ Curl_expire(conn->data, milli, EXPIRE_ASYNC_NAME);
return max;
}
@@ -373,7 +373,6 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
/* Wait for the name resolve query to complete. */
while(!result) {
struct timeval *tvp, tv, store;
- long timediff;
int itimeout;
int timeout_ms;
@@ -402,8 +401,13 @@ CURLcode Curl_resolver_wait_resolv(struct connectdata *conn,
result = CURLE_ABORTED_BY_CALLBACK;
else {
struct timeval now2 = Curl_tvnow();
- timediff = Curl_tvdiff(now2, now); /* spent time */
- timeout -= timediff?timediff:1; /* always deduct at least 1 */
+ time_t timediff = Curl_tvdiff(now2, now); /* spent time */
+ if(timediff <= 0)
+ timeout -= 1; /* always deduct at least 1 */
+ else if(timediff > timeout)
+ timeout = -1;
+ else
+ timeout -= (long)timediff;
now = now2; /* for next loop */
}
if(timeout < 0)
diff --git a/Utilities/cmcurl/lib/asyn-thread.c b/Utilities/cmcurl/lib/asyn-thread.c
index 26a15b110c..65fa6c5bec 100644
--- a/Utilities/cmcurl/lib/asyn-thread.c
+++ b/Utilities/cmcurl/lib/asyn-thread.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -22,6 +22,11 @@
#include "curl_setup.h"
+/***********************************************************************
+ * Only for threaded name resolves builds
+ **********************************************************************/
+#ifdef CURLRES_THREADED
+
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
@@ -74,11 +79,6 @@
#include "curl_memory.h"
#include "memdebug.h"
-/***********************************************************************
- * Only for threaded name resolves builds
- **********************************************************************/
-#ifdef CURLRES_THREADED
-
/*
* Curl_resolver_global_init()
* Called from curl_global_init() to initialize global resolver environment.
@@ -540,7 +540,7 @@ CURLcode Curl_resolver_is_resolved(struct connectdata *conn,
td->poll_interval = 250;
td->interval_end = elapsed + td->poll_interval;
- Curl_expire(conn->data, td->poll_interval);
+ Curl_expire(conn->data, td->poll_interval, EXPIRE_ASYNC_NAME);
}
return CURLE_OK;
diff --git a/Utilities/cmcurl/lib/conncache.c b/Utilities/cmcurl/lib/conncache.c
index 0590ec6311..c79d227640 100644
--- a/Utilities/cmcurl/lib/conncache.c
+++ b/Utilities/cmcurl/lib/conncache.c
@@ -72,13 +72,11 @@ static void bundle_destroy(struct connectbundle *cb_ptr)
/* Add a connection to a bundle */
static CURLcode bundle_add_conn(struct connectbundle *cb_ptr,
- struct connectdata *conn)
+ struct connectdata *conn)
{
- if(!Curl_llist_insert_next(&cb_ptr->conn_list, cb_ptr->conn_list.tail, conn))
- return CURLE_OUT_OF_MEMORY;
-
+ Curl_llist_insert_next(&cb_ptr->conn_list, cb_ptr->conn_list.tail, conn,
+ &conn->bundle_node);
conn->bundle = cb_ptr;
-
cb_ptr->num_connections++;
return CURLE_OK;
}
diff --git a/Utilities/cmcurl/lib/connect.c b/Utilities/cmcurl/lib/connect.c
index 63ec50fdc3..d4fd52b991 100644
--- a/Utilities/cmcurl/lib/connect.c
+++ b/Utilities/cmcurl/lib/connect.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -1070,7 +1070,7 @@ static CURLcode singleipconnect(struct connectdata *conn,
conn->connecttime = Curl_tvnow();
if(conn->num_addr > 1)
- Curl_expire_latest(data, conn->timeoutms_per_addr);
+ Curl_expire(data, conn->timeoutms_per_addr, EXPIRE_DNS_PER_NAME);
/* Connect TCP sockets, bind UDP */
if(!isconnected && (conn->socktype == SOCK_STREAM)) {
@@ -1169,7 +1169,7 @@ CURLcode Curl_connecthost(struct connectdata *conn, /* context */
conn->tempaddr[1] = NULL;
conn->tempsock[0] = CURL_SOCKET_BAD;
conn->tempsock[1] = CURL_SOCKET_BAD;
- Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT);
+ Curl_expire(conn->data, HAPPY_EYEBALLS_TIMEOUT, EXPIRE_HAPPY_EYEBALLS);
/* Max time for the next connection attempt */
conn->timeoutms_per_addr =
diff --git a/Utilities/cmcurl/lib/curl_endian.c b/Utilities/cmcurl/lib/curl_endian.c
index c2d21de5ee..c25db4956e 100644
--- a/Utilities/cmcurl/lib/curl_endian.c
+++ b/Utilities/cmcurl/lib/curl_endian.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -62,44 +62,6 @@ unsigned int Curl_read32_le(const unsigned char *buf)
((unsigned int)buf[2] << 16) | ((unsigned int)buf[3] << 24);
}
-#if (CURL_SIZEOF_CURL_OFF_T > 4)
-/*
- * Curl_read64_le()
- *
- * This function converts a 64-bit integer from the little endian format, as
- * used in the incoming package to whatever endian format we're using
- * natively.
- *
- * Parameters:
- *
- * buf [in] - A pointer to a 8 byte buffer.
- *
- * Returns the integer.
- */
-#if defined(HAVE_LONGLONG)
-unsigned long long Curl_read64_le(const unsigned char *buf)
-{
- return ((unsigned long long)buf[0]) |
- ((unsigned long long)buf[1] << 8) |
- ((unsigned long long)buf[2] << 16) |
- ((unsigned long long)buf[3] << 24) |
- ((unsigned long long)buf[4] << 32) |
- ((unsigned long long)buf[5] << 40) |
- ((unsigned long long)buf[6] << 48) |
- ((unsigned long long)buf[7] << 56);
-}
-#else
-unsigned __int64 Curl_read64_le(const unsigned char *buf)
-{
- return ((unsigned __int64)buf[0]) | ((unsigned __int64)buf[1] << 8) |
- ((unsigned __int64)buf[2] << 16) | ((unsigned __int64)buf[3] << 24) |
- ((unsigned __int64)buf[4] << 32) | ((unsigned __int64)buf[5] << 40) |
- ((unsigned __int64)buf[6] << 48) | ((unsigned __int64)buf[7] << 56);
-}
-#endif
-
-#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */
-
/*
* Curl_read16_be()
*
@@ -120,80 +82,6 @@ unsigned short Curl_read16_be(const unsigned char *buf)
}
/*
- * Curl_read32_be()
- *
- * This function converts a 32-bit integer from the big endian format, as
- * used in the incoming package to whatever endian format we're using
- * natively.
- *
- * Parameters:
- *
- * buf [in] - A pointer to a 4 byte buffer.
- *
- * Returns the integer.
- */
-unsigned int Curl_read32_be(const unsigned char *buf)
-{
- return ((unsigned int)buf[0] << 24) | ((unsigned int)buf[1] << 16) |
- ((unsigned int)buf[2] << 8) | ((unsigned int)buf[3]);
-}
-
-#if (CURL_SIZEOF_CURL_OFF_T > 4)
-/*
- * Curl_read64_be()
- *
- * This function converts a 64-bit integer from the big endian format, as
- * used in the incoming package to whatever endian format we're using
- * natively.
- *
- * Parameters:
- *
- * buf [in] - A pointer to a 8 byte buffer.
- *
- * Returns the integer.
- */
-#if defined(HAVE_LONGLONG)
-unsigned long long Curl_read64_be(const unsigned char *buf)
-{
- return ((unsigned long long)buf[0] << 56) |
- ((unsigned long long)buf[1] << 48) |
- ((unsigned long long)buf[2] << 40) |
- ((unsigned long long)buf[3] << 32) |
- ((unsigned long long)buf[4] << 24) |
- ((unsigned long long)buf[5] << 16) |
- ((unsigned long long)buf[6] << 8) |
- ((unsigned long long)buf[7]);
-}
-#else
-unsigned __int64 Curl_read64_be(const unsigned char *buf)
-{
- return ((unsigned __int64)buf[0] << 56) | ((unsigned __int64)buf[1] << 48) |
- ((unsigned __int64)buf[2] << 40) | ((unsigned __int64)buf[3] << 32) |
- ((unsigned __int64)buf[4] << 24) | ((unsigned __int64)buf[5] << 16) |
- ((unsigned __int64)buf[6] << 8) | ((unsigned __int64)buf[7]);
-}
-#endif
-
-#endif /* CURL_SIZEOF_CURL_OFF_T > 4 */
-
-/*
- * Curl_write16_le()
- *
- * This function converts a 16-bit integer from the native endian format,
- * to little endian format ready for sending down the wire.
- *
- * Parameters:
- *
- * value [in] - The 16-bit integer value.
- * buffer [in] - A pointer to the output buffer.
- */
-void Curl_write16_le(const short value, unsigned char *buffer)
-{
- buffer[0] = (char)(value & 0x00FF);
- buffer[1] = (char)((value & 0xFF00) >> 8);
-}
-
-/*
* Curl_write32_le()
*
* This function converts a 32-bit integer from the native endian format,
diff --git a/Utilities/cmcurl/lib/curl_endian.h b/Utilities/cmcurl/lib/curl_endian.h
index 8a2b07ad85..4f345a6a22 100644
--- a/Utilities/cmcurl/lib/curl_endian.h
+++ b/Utilities/cmcurl/lib/curl_endian.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -28,33 +28,9 @@ unsigned short Curl_read16_le(const unsigned char *buf);
/* Converts a 32-bit integer from little endian */
unsigned int Curl_read32_le(const unsigned char *buf);
-#if (CURL_SIZEOF_CURL_OFF_T > 4)
-/* Converts a 64-bit integer from little endian */
-#if defined(HAVE_LONGLONG)
-unsigned long long Curl_read64_le(const unsigned char *buf);
-#else
-unsigned __int64 Curl_read64_le(const unsigned char *buf);
-#endif
-#endif
-
/* Converts a 16-bit integer from big endian */
unsigned short Curl_read16_be(const unsigned char *buf);
-/* Converts a 32-bit integer from big endian */
-unsigned int Curl_read32_be(const unsigned char *buf);
-
-#if (CURL_SIZEOF_CURL_OFF_T > 4)
-/* Converts a 64-bit integer from big endian */
-#if defined(HAVE_LONGLONG)
-unsigned long long Curl_read64_be(const unsigned char *buf);
-#else
-unsigned __int64 Curl_read64_be(const unsigned char *buf);
-#endif
-#endif
-
-/* Converts a 16-bit integer to little endian */
-void Curl_write16_le(const short value, unsigned char *buffer);
-
/* Converts a 32-bit integer to little endian */
void Curl_write32_le(const int value, unsigned char *buffer);
diff --git a/Utilities/cmcurl/lib/curl_md4.h b/Utilities/cmcurl/lib/curl_md4.h
index 8c26d1222a..e0690416dd 100644
--- a/Utilities/cmcurl/lib/curl_md4.h
+++ b/Utilities/cmcurl/lib/curl_md4.h
@@ -24,12 +24,12 @@
#include "curl_setup.h"
-/* NSS and OS/400 crypto library do not provide the MD4 hash algorithm, so
- * that we have a local implementation of it */
-#if defined(USE_NSS) || defined(USE_OS400CRYPTO)
+#if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \
+ (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C))
void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len);
-#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) */
+#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) ||
+ (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */
#endif /* HEADER_CURL_MD4_H */
diff --git a/Utilities/cmcurl/lib/curl_ntlm_core.c b/Utilities/cmcurl/lib/curl_ntlm_core.c
index fb43dda193..aea545295e 100644
--- a/Utilities/cmcurl/lib/curl_ntlm_core.c
+++ b/Utilities/cmcurl/lib/curl_ntlm_core.c
@@ -80,6 +80,9 @@
# include <mbedtls/des.h>
# include <mbedtls/md4.h>
+# if !defined(MBEDTLS_MD4_C)
+# include "curl_md4.h"
+# endif
#elif defined(USE_NSS)
@@ -519,7 +522,7 @@ static void ascii_uppercase_to_unicode_le(unsigned char *dest,
{
size_t i;
for(i = 0; i < srclen; i++) {
- dest[2 * i] = (unsigned char)(toupper(src[i]));
+ dest[2 * i] = (unsigned char)(Curl_raw_toupper(src[i]));
dest[2 * i + 1] = '\0';
}
}
@@ -568,10 +571,11 @@ CURLcode Curl_ntlm_core_mk_nt_hash(struct Curl_easy *data,
gcry_md_write(MD4pw, pw, 2 * len);
memcpy(ntbuffer, gcry_md_read(MD4pw, 0), MD4_DIGEST_LENGTH);
gcry_md_close(MD4pw);
+#elif defined(USE_NSS) || defined(USE_OS400CRYPTO) || \
+ (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C))
+ Curl_md4it(ntbuffer, pw, 2 * len);
#elif defined(USE_MBEDTLS)
mbedtls_md4(pw, 2 * len, ntbuffer);
-#elif defined(USE_NSS) || defined(USE_OS400CRYPTO)
- Curl_md4it(ntbuffer, pw, 2 * len);
#elif defined(USE_DARWINSSL)
(void)CC_MD4(pw, (CC_LONG)(2 * len), ntbuffer);
#elif defined(USE_WIN32_CRYPTO)
diff --git a/Utilities/cmcurl/lib/curl_rtmp.c b/Utilities/cmcurl/lib/curl_rtmp.c
index 06dd047a40..87a6caf9e6 100644
--- a/Utilities/cmcurl/lib/curl_rtmp.c
+++ b/Utilities/cmcurl/lib/curl_rtmp.c
@@ -25,6 +25,7 @@
#ifdef USE_LIBRTMP
+#include "curl_rtmp.h"
#include "urldata.h"
#include "nonblock.h" /* for curlx_nonblock */
#include "progress.h" /* for Curl_pgrsSetUploadSize */
diff --git a/Utilities/cmcurl/lib/curl_sasl.c b/Utilities/cmcurl/lib/curl_sasl.c
index b3789dab00..bd574b5e2a 100644
--- a/Utilities/cmcurl/lib/curl_sasl.c
+++ b/Utilities/cmcurl/lib/curl_sasl.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2012 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2012 - 2017, 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
@@ -415,7 +415,6 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
conn->host.name;
const long int port = SSL_IS_PROXY() ? conn->port : conn->remote_port;
#if !defined(CURL_DISABLE_CRYPTO_AUTH)
- char *serverdata;
char *chlg = NULL;
size_t chlglen = 0;
#endif
@@ -424,6 +423,10 @@ CURLcode Curl_sasl_continue(struct SASL *sasl, struct connectdata *conn,
data->set.str[STRING_SERVICE_NAME] :
sasl->params->service;
#endif
+#if !defined(CURL_DISABLE_CRYPTO_AUTH) || defined(USE_KERBEROS5) || \
+ defined(USE_NTLM)
+ char *serverdata;
+#endif
size_t len = 0;
*progress = SASL_INPROGRESS;
diff --git a/Utilities/cmcurl/lib/curl_setup.h b/Utilities/cmcurl/lib/curl_setup.h
index 6ab18cd1f2..a6268adf23 100644
--- a/Utilities/cmcurl/lib/curl_setup.h
+++ b/Utilities/cmcurl/lib/curl_setup.h
@@ -603,11 +603,15 @@ int netware_init(void);
#endif
#endif
-#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H)
+#if defined(HAVE_LIBIDN2) && defined(HAVE_IDN2_H) && !defined(USE_WIN32_IDN)
/* The lib and header are present */
#define USE_LIBIDN2
#endif
+#if defined(USE_LIBIDN2) && defined(USE_WIN32_IDN)
+#error "Both libidn2 and WinIDN are enabled, choose one."
+#endif
+
#ifndef SIZEOF_TIME_T
/* assume default size of time_t to be 32 bit */
#define SIZEOF_TIME_T 4
@@ -638,14 +642,14 @@ int netware_init(void);
#if !defined(CURL_DISABLE_NTLM) && !defined(CURL_DISABLE_CRYPTO_AUTH)
#if defined(USE_OPENSSL) || defined(USE_WINDOWS_SSPI) || \
defined(USE_GNUTLS) || defined(USE_NSS) || defined(USE_DARWINSSL) || \
- defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO)
+ defined(USE_OS400CRYPTO) || defined(USE_WIN32_CRYPTO) || \
+ defined(USE_MBEDTLS)
#define USE_NTLM
-#elif defined(USE_MBEDTLS)
+# if defined(USE_MBEDTLS)
+/* Get definition of MBEDTLS_MD4_C */
# include <mbedtls/md4.h>
-# if defined(MBEDTLS_MD4_C)
-#define USE_NTLM
# endif
#endif
diff --git a/Utilities/cmcurl/lib/curl_setup_once.h b/Utilities/cmcurl/lib/curl_setup_once.h
index 4da83499af..684187caee 100644
--- a/Utilities/cmcurl/lib/curl_setup_once.h
+++ b/Utilities/cmcurl/lib/curl_setup_once.h
@@ -196,7 +196,7 @@ struct timeval {
/* */
#else
#define swrite(x,y,z) (ssize_t)send((SEND_TYPE_ARG1)(x), \
- (SEND_TYPE_ARG2)(y), \
+ (SEND_QUAL_ARG2 SEND_TYPE_ARG2)(y), \
(SEND_TYPE_ARG3)(z), \
(SEND_TYPE_ARG4)(SEND_4TH_ARG))
#endif
diff --git a/Utilities/cmcurl/lib/dotdot.c b/Utilities/cmcurl/lib/dotdot.c
index ea7c8a04f6..20603bcab7 100644
--- a/Utilities/cmcurl/lib/dotdot.c
+++ b/Utilities/cmcurl/lib/dotdot.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -147,6 +147,7 @@ char *Curl_dedotdotify(const char *input)
else if(!strcmp(".", clone) || !strcmp("..", clone)) {
*clone=0;
+ *out=0;
}
else {
diff --git a/Utilities/cmcurl/lib/easy.c b/Utilities/cmcurl/lib/easy.c
index 2b5f972e12..2b1ce9e8ab 100644
--- a/Utilities/cmcurl/lib/easy.c
+++ b/Utilities/cmcurl/lib/easy.c
@@ -561,7 +561,7 @@ static void events_setup(struct Curl_multi *multi, struct events *ev)
static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
{
bool done = FALSE;
- CURLMcode mcode;
+ CURLMcode mcode = CURLM_OK;
CURLcode result = CURLE_OK;
while(!done) {
@@ -615,12 +615,18 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
}
}
- if(!ev->msbump)
+ if(!ev->msbump) {
/* If nothing updated the timeout, we decrease it by the spent time.
* If it was updated, it has the new timeout time stored already.
*/
- ev->ms += (long)curlx_tvdiff(after, before);
-
+ time_t timediff = curlx_tvdiff(after, before);
+ if(timediff > 0) {
+ if(timediff > ev->ms)
+ ev->ms = 0;
+ else
+ ev->ms -= (long)timediff;
+ }
+ }
}
else
return CURLE_RECV_ERROR;
@@ -870,7 +876,7 @@ struct Curl_easy *curl_easy_duphandle(struct Curl_easy *data)
* the likeliness of us forgetting to init a buffer here in the future.
*/
outcurl->set.buffer_size = data->set.buffer_size;
- outcurl->state.buffer = malloc(CURL_BUFSIZE(outcurl->set.buffer_size) + 1);
+ outcurl->state.buffer = malloc(outcurl->set.buffer_size + 1);
if(!outcurl->state.buffer)
goto fail;
@@ -1044,7 +1050,7 @@ CURLcode curl_easy_pause(struct Curl_easy *data, int action)
if(!result &&
((newstate&(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) !=
(KEEP_RECV_PAUSE|KEEP_SEND_PAUSE)) )
- Curl_expire(data, 0); /* get this handle going again */
+ Curl_expire(data, 0, EXPIRE_RUN_NOW); /* get this handle going again */
return result;
}
diff --git a/Utilities/cmcurl/lib/file.c b/Utilities/cmcurl/lib/file.c
index b26bdeafc3..c804d75e11 100644
--- a/Utilities/cmcurl/lib/file.c
+++ b/Utilities/cmcurl/lib/file.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -311,7 +311,6 @@ static CURLcode file_upload(struct connectdata *conn)
size_t nread;
size_t nwrite;
curl_off_t bytecount = 0;
- struct timeval now = Curl_tvnow();
struct_stat file_stat;
const char *buf2;
@@ -360,7 +359,7 @@ static CURLcode file_upload(struct connectdata *conn)
while(!result) {
int readcount;
- result = Curl_fillreadbuffer(conn, BUFSIZE, &readcount);
+ result = Curl_fillreadbuffer(conn, (int)data->set.buffer_size, &readcount);
if(result)
break;
@@ -399,7 +398,7 @@ static CURLcode file_upload(struct connectdata *conn)
if(Curl_pgrsUpdate(conn))
result = CURLE_ABORTED_BY_CALLBACK;
else
- result = Curl_speedcheck(data, now);
+ result = Curl_speedcheck(data, Curl_tvnow());
}
if(!result && Curl_pgrsUpdate(conn))
result = CURLE_ABORTED_BY_CALLBACK;
@@ -436,7 +435,6 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
char *buf = data->state.buffer;
curl_off_t bytecount = 0;
int fd;
- struct timeval now = Curl_tvnow();
struct FILEPROTO *file;
*done = TRUE; /* unconditionally */
@@ -475,9 +473,10 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
time_t filetime;
struct tm buffer;
const struct tm *tm = &buffer;
- snprintf(buf, CURL_BUFSIZE(data->set.buffer_size),
+ char header[80];
+ snprintf(header, sizeof(header),
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", expected_size);
- result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
+ result = Curl_client_write(conn, CLIENTWRITE_BOTH, header, 0);
if(result)
return result;
@@ -492,7 +491,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
return result;
/* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
- snprintf(buf, BUFSIZE-1,
+ snprintf(header, sizeof(header),
"Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
tm->tm_mday,
@@ -557,12 +556,11 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
size_t bytestoread;
if(size_known) {
- bytestoread =
- (expected_size < CURL_OFF_T_C(BUFSIZE) - CURL_OFF_T_C(1)) ?
- curlx_sotouz(expected_size) : BUFSIZE - 1;
+ bytestoread = (expected_size < data->set.buffer_size) ?
+ curlx_sotouz(expected_size) : (size_t)data->set.buffer_size;
}
else
- bytestoread = BUFSIZE-1;
+ bytestoread = data->set.buffer_size-1;
nread = read(fd, buf, bytestoread);
@@ -585,7 +583,7 @@ static CURLcode file_do(struct connectdata *conn, bool *done)
if(Curl_pgrsUpdate(conn))
result = CURLE_ABORTED_BY_CALLBACK;
else
- result = Curl_speedcheck(data, now);
+ result = Curl_speedcheck(data, Curl_tvnow());
}
if(Curl_pgrsUpdate(conn))
result = CURLE_ABORTED_BY_CALLBACK;
diff --git a/Utilities/cmcurl/lib/fileinfo.c b/Utilities/cmcurl/lib/fileinfo.c
index 144c65b1d8..3872988474 100644
--- a/Utilities/cmcurl/lib/fileinfo.c
+++ b/Utilities/cmcurl/lib/fileinfo.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010 - 2017, 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
@@ -28,23 +28,19 @@
/* The last #include file should be: */
#include "memdebug.h"
-struct curl_fileinfo *Curl_fileinfo_alloc(void)
+struct fileinfo *Curl_fileinfo_alloc(void)
{
- struct curl_fileinfo *tmp = malloc(sizeof(struct curl_fileinfo));
- if(!tmp)
- return NULL;
- memset(tmp, 0, sizeof(struct curl_fileinfo));
- return tmp;
+ return calloc(1, sizeof(struct fileinfo));
}
void Curl_fileinfo_dtor(void *user, void *element)
{
- struct curl_fileinfo *finfo = element;
+ struct fileinfo *finfo = element;
(void) user;
if(!finfo)
return;
- Curl_safefree(finfo->b_data);
+ Curl_safefree(finfo->info.b_data);
free(finfo);
}
diff --git a/Utilities/cmcurl/lib/fileinfo.h b/Utilities/cmcurl/lib/fileinfo.h
index 5324f1a404..c5d0ee5b64 100644
--- a/Utilities/cmcurl/lib/fileinfo.h
+++ b/Utilities/cmcurl/lib/fileinfo.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 2010, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2010, 2017, 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
@@ -23,11 +23,15 @@
***************************************************************************/
#include <curl/curl.h>
+#include "llist.h"
-struct curl_fileinfo *Curl_fileinfo_alloc(void);
+struct fileinfo {
+ struct curl_fileinfo info;
+ struct curl_llist_element list;
+};
-void Curl_fileinfo_dtor(void *, void *);
+struct fileinfo *Curl_fileinfo_alloc(void);
-struct curl_fileinfo *Curl_fileinfo_dup(const struct curl_fileinfo *src);
+void Curl_fileinfo_dtor(void *, void *);
#endif /* HEADER_CURL_FILEINFO_H */
diff --git a/Utilities/cmcurl/lib/formdata.c b/Utilities/cmcurl/lib/formdata.c
index 2a934344eb..e48a6276c6 100644
--- a/Utilities/cmcurl/lib/formdata.c
+++ b/Utilities/cmcurl/lib/formdata.c
@@ -48,15 +48,12 @@ static char *Curl_basename(char *path);
#endif
static size_t readfromfile(struct Form *form, char *buffer, size_t size);
-static char *formboundary(struct Curl_easy *data);
+static CURLcode formboundary(struct Curl_easy *data, char *buffer, size_t len);
/* What kind of Content-Type to use on un-specified files with unrecognized
extensions. */
#define HTTPPOST_CONTENTTYPE_DEFAULT "application/octet-stream"
-#define FORM_FILE_SEPARATOR ','
-#define FORM_TYPE_SEPARATOR ';'
-
#define HTTPPOST_PTRNAME CURL_HTTPPOST_PTRNAME
#define HTTPPOST_FILENAME CURL_HTTPPOST_FILENAME
#define HTTPPOST_PTRCONTENTS CURL_HTTPPOST_PTRCONTENTS
@@ -99,7 +96,7 @@ AddHttpPost(char *name, size_t namelength,
post->contenttype = contenttype;
post->contentheader = contentHeader;
post->showfilename = showfilename;
- post->userp = userp,
+ post->userp = userp;
post->flags = flags | CURL_HTTPPOST_LARGE;
}
else
@@ -1162,20 +1159,19 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
struct FormData *firstform;
struct curl_httppost *file;
CURLcode result = CURLE_OK;
-
curl_off_t size = 0; /* support potentially ENORMOUS formposts */
- char *boundary;
- char *fileboundary = NULL;
+ char fileboundary[42];
struct curl_slist *curList;
+ char boundary[42];
*finalform = NULL; /* default form is empty */
if(!post)
return result; /* no input => no output! */
- boundary = formboundary(data);
- if(!boundary)
- return CURLE_OUT_OF_MEMORY;
+ result = formboundary(data, boundary, sizeof(boundary));
+ if(result)
+ return result;
/* Make the first line of the output */
result = AddFormDataf(&form, NULL,
@@ -1185,7 +1181,6 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
boundary);
if(result) {
- free(boundary);
return result;
}
/* we DO NOT include that line in the total size of the POST, since it'll be
@@ -1228,10 +1223,8 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
/* If used, this is a link to more file names, we must then do
the magic to include several files with the same field name */
- free(fileboundary);
- fileboundary = formboundary(data);
- if(!fileboundary) {
- result = CURLE_OUT_OF_MEMORY;
+ result = formboundary(data, fileboundary, sizeof(fileboundary));
+ if(result) {
break;
}
@@ -1382,16 +1375,10 @@ CURLcode Curl_getformdata(struct Curl_easy *data,
if(result) {
Curl_formclean(&firstform);
- free(fileboundary);
- free(boundary);
return result;
}
*sizep = size;
-
- free(fileboundary);
- free(boundary);
-
*finalform = firstform;
return result;
@@ -1565,16 +1552,18 @@ char *Curl_formpostheader(void *formp, size_t *len)
* formboundary() creates a suitable boundary string and returns an allocated
* one.
*/
-static char *formboundary(struct Curl_easy *data)
+static CURLcode formboundary(struct Curl_easy *data,
+ char *buffer, size_t buflen)
{
/* 24 dashes and 16 hexadecimal digits makes 64 bit (18446744073709551615)
combinations */
- unsigned int rnd[2];
- CURLcode result = Curl_rand(data, &rnd[0], 2);
- if(result)
- return NULL;
+ if(buflen < 41)
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ memset(buffer, '-', 24);
+ Curl_rand_hex(data, (unsigned char *)&buffer[24], 17);
- return aprintf("------------------------%08x%08x", rnd[0], rnd[1]);
+ return CURLE_OK;
}
#else /* CURL_DISABLE_HTTP */
diff --git a/Utilities/cmcurl/lib/ftp.c b/Utilities/cmcurl/lib/ftp.c
index a5ca2ab985..783dbe1246 100644
--- a/Utilities/cmcurl/lib/ftp.c
+++ b/Utilities/cmcurl/lib/ftp.c
@@ -580,10 +580,8 @@ static CURLcode AllowServerConnect(struct connectdata *conn, bool *connected)
else {
/* Add timeout to multi handle and break out of the loop */
if(!result && *connected == FALSE) {
- if(data->set.accepttimeout > 0)
- Curl_expire(data, data->set.accepttimeout);
- else
- Curl_expire(data, DEFAULT_ACCEPT_TIMEOUT);
+ Curl_expire(data, data->set.accepttimeout > 0 ?
+ data->set.accepttimeout: DEFAULT_ACCEPT_TIMEOUT, 0);
}
}
@@ -1681,8 +1679,9 @@ static CURLcode ftp_state_ul_setup(struct connectdata *conn,
/* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
do {
size_t readthisamountnow =
- (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
- BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
+ (data->state.resume_from - passed > data->set.buffer_size) ?
+ (size_t)data->set.buffer_size :
+ curlx_sotouz(data->state.resume_from - passed);
size_t actuallyread =
data->state.fread_func(data->state.buffer, 1, readthisamountnow,
@@ -2101,17 +2100,17 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
/* we got a time. Format should be: "YYYYMMDDHHMMSS[.sss]" where the
last .sss part is optional and means fractions of a second */
int year, month, day, hour, minute, second;
- char *buf = data->state.buffer;
- if(6 == sscanf(buf+4, "%04d%02d%02d%02d%02d%02d",
+ if(6 == sscanf(&data->state.buffer[4], "%04d%02d%02d%02d%02d%02d",
&year, &month, &day, &hour, &minute, &second)) {
/* we have a time, reformat it */
+ char timebuf[24];
time_t secs=time(NULL);
- /* using the good old yacc/bison yuck */
- snprintf(buf, CURL_BUFSIZE(conn->data->set.buffer_size),
+
+ snprintf(timebuf, sizeof(timebuf),
"%04d%02d%02d %02d:%02d:%02d GMT",
year, month, day, hour, minute, second);
/* now, convert this into a time() value: */
- data->info.filetime = (long)curl_getdate(buf, &secs);
+ data->info.filetime = (long)curl_getdate(timebuf, &secs);
}
#ifdef CURL_FTP_HTTPSTYLE_HEAD
@@ -2122,6 +2121,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
ftpc->file &&
data->set.get_filetime &&
(data->info.filetime>=0) ) {
+ char headerbuf[128];
time_t filetime = (time_t)data->info.filetime;
struct tm buffer;
const struct tm *tm = &buffer;
@@ -2131,7 +2131,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
return result;
/* format: "Tue, 15 Nov 1994 12:45:26" */
- snprintf(buf, BUFSIZE-1,
+ snprintf(headerbuf, sizeof(headerbuf),
"Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
tm->tm_mday,
@@ -2140,7 +2140,7 @@ static CURLcode ftp_state_mdtm_resp(struct connectdata *conn,
tm->tm_hour,
tm->tm_min,
tm->tm_sec);
- result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
+ result = Curl_client_write(conn, CLIENTWRITE_BOTH, headerbuf, 0);
if(result)
return result;
} /* end of a ridiculous amount of conditionals */
@@ -2318,9 +2318,10 @@ static CURLcode ftp_state_size_resp(struct connectdata *conn,
if(instate == FTP_SIZE) {
#ifdef CURL_FTP_HTTPSTYLE_HEAD
if(-1 != filesize) {
- snprintf(buf, CURL_BUFSIZE(data->set.buffer_size),
+ char clbuf[128];
+ snprintf(clbuf, sizeof(clbuf),
"Content-Length: %" CURL_FORMAT_CURL_OFF_T "\r\n", filesize);
- result = Curl_client_write(conn, CLIENTWRITE_BOTH, buf, 0);
+ result = Curl_client_write(conn, CLIENTWRITE_BOTH, clbuf, 0);
if(result)
return result;
}
@@ -2420,7 +2421,6 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
CURLcode result = CURLE_OK;
struct Curl_easy *data = conn->data;
struct FTP *ftp = data->req.protop;
- char *buf = data->state.buffer;
if((ftpcode == 150) || (ftpcode == 125)) {
@@ -2464,6 +2464,7 @@ static CURLcode ftp_state_get_resp(struct connectdata *conn,
*
* Example D above makes this parsing a little tricky */
char *bytes;
+ char *buf = data->state.buffer;
bytes=strstr(buf, " bytes");
if(bytes--) {
long in=(long)(bytes-buf);
@@ -2822,7 +2823,7 @@ static CURLcode ftp_statemach_act(struct connectdata *conn)
case FTP_PWD:
if(ftpcode == 257) {
char *ptr=&data->state.buffer[4]; /* start on the first letter */
- const size_t buf_size = CURL_BUFSIZE(data->set.buffer_size);
+ const size_t buf_size = data->set.buffer_size;
char *dir;
char *store;
@@ -3587,7 +3588,7 @@ static CURLcode ftp_do_more(struct connectdata *conn, int *completep)
if(conn->tunnel_state[SECONDARYSOCKET] == TUNNEL_CONNECT) {
/* As we're in TUNNEL_CONNECT state now, we know the proxy name and port
aren't used so we blank their arguments. TODO: make this nicer */
- result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0, FALSE);
+ result = Curl_proxyCONNECT(conn, SECONDARYSOCKET, NULL, 0);
return result;
}
diff --git a/Utilities/cmcurl/lib/ftplistparser.c b/Utilities/cmcurl/lib/ftplistparser.c
index bc186805f8..2acce31d8f 100644
--- a/Utilities/cmcurl/lib/ftplistparser.c
+++ b/Utilities/cmcurl/lib/ftplistparser.c
@@ -165,7 +165,7 @@ struct ftp_parselist_data {
} state;
CURLcode error;
- struct curl_fileinfo *file_data;
+ struct fileinfo *file_data;
unsigned int item_length;
size_t item_offset;
struct {
@@ -275,7 +275,7 @@ static void PL_ERROR(struct connectdata *conn, CURLcode err)
}
static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
- struct curl_fileinfo *finfo)
+ struct fileinfo *infop)
{
curl_fnmatch_callback compare;
struct WildcardData *wc = &conn->data->wildcard;
@@ -283,6 +283,7 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
struct curl_llist *llist = &wc->filelist;
struct ftp_parselist_data *parser = tmpdata->parser;
bool add = TRUE;
+ struct curl_fileinfo *finfo = &infop->info;
/* move finfo pointers to b_data */
char *str = finfo->b_data;
@@ -316,11 +317,7 @@ static CURLcode ftp_pl_insert_finfo(struct connectdata *conn,
}
if(add) {
- if(!Curl_llist_insert_next(llist, llist->tail, finfo)) {
- Curl_fileinfo_dtor(NULL, finfo);
- tmpdata->parser->file_data = NULL;
- return CURLE_OUT_OF_MEMORY;
- }
+ Curl_llist_insert_next(llist, llist->tail, finfo, &infop->list);
}
else {
Curl_fileinfo_dtor(NULL, finfo);
@@ -337,6 +334,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
struct connectdata *conn = (struct connectdata *)connptr;
struct ftp_wc_tmpdata *tmpdata = conn->data->wildcard.tmp;
struct ftp_parselist_data *parser = tmpdata->parser;
+ struct fileinfo *infop;
struct curl_fileinfo *finfo;
unsigned long i = 0;
CURLcode result;
@@ -366,17 +364,18 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
parser->error = CURLE_OUT_OF_MEMORY;
return bufflen;
}
- parser->file_data->b_data = malloc(FTP_BUFFER_ALLOCSIZE);
- if(!parser->file_data->b_data) {
+ parser->file_data->info.b_data = malloc(FTP_BUFFER_ALLOCSIZE);
+ if(!parser->file_data->info.b_data) {
PL_ERROR(conn, CURLE_OUT_OF_MEMORY);
return bufflen;
}
- parser->file_data->b_size = FTP_BUFFER_ALLOCSIZE;
+ parser->file_data->info.b_size = FTP_BUFFER_ALLOCSIZE;
parser->item_offset = 0;
parser->item_length = 0;
}
- finfo = parser->file_data;
+ infop = parser->file_data;
+ finfo = &infop->info;
finfo->b_data[finfo->b_used++] = c;
if(finfo->b_used >= finfo->b_size - 1) {
@@ -498,8 +497,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
PL_ERROR(conn, CURLE_FTP_BAD_FILE_LIST);
return bufflen;
}
- parser->file_data->flags |= CURLFINFOFLAG_KNOWN_PERM;
- parser->file_data->perm = perm;
+ parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_PERM;
+ parser->file_data->info.perm = perm;
parser->offsets.perm = parser->item_offset;
parser->item_length = 0;
@@ -530,8 +529,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
hlinks = strtol(finfo->b_data + parser->item_offset, &p, 10);
if(p[0] == '\0' && hlinks != LONG_MAX && hlinks != LONG_MIN) {
- parser->file_data->flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT;
- parser->file_data->hardlinks = hlinks;
+ parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_HLINKCOUNT;
+ parser->file_data->info.hardlinks = hlinks;
}
parser->item_length = 0;
parser->item_offset = 0;
@@ -613,8 +612,8 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
fsize = curlx_strtoofft(finfo->b_data+parser->item_offset, &p, 10);
if(p[0] == '\0' && fsize != CURL_OFF_T_MAX &&
fsize != CURL_OFF_T_MIN) {
- parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE;
- parser->file_data->size = fsize;
+ parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE;
+ parser->file_data->info.size = fsize;
}
parser->item_length = 0;
parser->item_offset = 0;
@@ -731,7 +730,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.filename = parser->item_offset;
parser->state.UNIX.main = PL_UNIX_FILETYPE;
- result = ftp_pl_insert_finfo(conn, finfo);
+ result = ftp_pl_insert_finfo(conn, infop);
if(result) {
PL_ERROR(conn, result);
return bufflen;
@@ -743,7 +742,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.filename = parser->item_offset;
parser->state.UNIX.main = PL_UNIX_FILETYPE;
- result = ftp_pl_insert_finfo(conn, finfo);
+ result = ftp_pl_insert_finfo(conn, infop);
if(result) {
PL_ERROR(conn, result);
return bufflen;
@@ -838,7 +837,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
else if(c == '\n') {
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.symlink_target = parser->item_offset;
- result = ftp_pl_insert_finfo(conn, finfo);
+ result = ftp_pl_insert_finfo(conn, infop);
if(result) {
PL_ERROR(conn, result);
return bufflen;
@@ -850,7 +849,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
if(c == '\n') {
finfo->b_data[parser->item_offset + parser->item_length - 1] = 0;
parser->offsets.symlink_target = parser->item_offset;
- result = ftp_pl_insert_finfo(conn, finfo);
+ result = ftp_pl_insert_finfo(conn, infop);
if(result) {
PL_ERROR(conn, result);
return bufflen;
@@ -953,10 +952,10 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
return bufflen;
}
/* correct file type */
- parser->file_data->filetype = CURLFILETYPE_FILE;
+ parser->file_data->info.filetype = CURLFILETYPE_FILE;
}
- parser->file_data->flags |= CURLFINFOFLAG_KNOWN_SIZE;
+ parser->file_data->info.flags |= CURLFINFOFLAG_KNOWN_SIZE;
parser->item_length = 0;
parser->state.NT.main = PL_WINNT_FILENAME;
parser->state.NT.sub.filename = PL_WINNT_FILENAME_PRESPACE;
@@ -983,7 +982,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
parser->offsets.filename = parser->item_offset;
finfo->b_data[finfo->b_used - 1] = 0;
parser->offsets.filename = parser->item_offset;
- result = ftp_pl_insert_finfo(conn, finfo);
+ result = ftp_pl_insert_finfo(conn, infop);
if(result) {
PL_ERROR(conn, result);
return bufflen;
@@ -995,7 +994,7 @@ size_t Curl_ftp_parselist(char *buffer, size_t size, size_t nmemb,
case PL_WINNT_FILENAME_WINEOL:
if(c == '\n') {
parser->offsets.filename = parser->item_offset;
- result = ftp_pl_insert_finfo(conn, finfo);
+ result = ftp_pl_insert_finfo(conn, infop);
if(result) {
PL_ERROR(conn, result);
return bufflen;
diff --git a/Utilities/cmcurl/lib/hash.c b/Utilities/cmcurl/lib/hash.c
index b7305a572a..6afeaa12c8 100644
--- a/Utilities/cmcurl/lib/hash.c
+++ b/Utilities/cmcurl/lib/hash.c
@@ -124,17 +124,9 @@ Curl_hash_add(struct curl_hash *h, void *key, size_t key_len, void *p)
he = mk_hash_element(key, key_len, p);
if(he) {
- if(Curl_llist_insert_next(l, l->tail, he)) {
- ++h->size;
- return p; /* return the new entry */
- }
- /*
- * Couldn't insert it, destroy the 'he' element and the key again. We
- * don't call hash_element_dtor() since that would also call the
- * "destructor" for the actual data 'p'. When we fail, we shall not touch
- * that data.
- */
- free(he);
+ Curl_llist_insert_next(l, l->tail, he, &he->list);
+ ++h->size;
+ return p; /* return the new entry */
}
return NULL; /* failure */
diff --git a/Utilities/cmcurl/lib/hash.h b/Utilities/cmcurl/lib/hash.h
index a345c8c87e..90a25d1ca3 100644
--- a/Utilities/cmcurl/lib/hash.h
+++ b/Utilities/cmcurl/lib/hash.h
@@ -57,6 +57,7 @@ struct curl_hash {
};
struct curl_hash_element {
+ struct curl_llist_element list;
void *ptr;
size_t key_len;
char key[1]; /* allocated memory following the struct */
diff --git a/Utilities/cmcurl/lib/hostip.c b/Utilities/cmcurl/lib/hostip.c
index ed18763fda..619ec84b5e 100644
--- a/Utilities/cmcurl/lib/hostip.c
+++ b/Utilities/cmcurl/lib/hostip.c
@@ -538,7 +538,6 @@ RETSIGTYPE alarmfunc(int sig)
/* this is for "-ansi -Wall -pedantic" to stop complaining! (rabe) */
(void)sig;
siglongjmp(curl_jmpenv, 1);
- return;
}
#endif /* USE_ALARM_TIMEOUT */
@@ -597,7 +596,7 @@ int Curl_resolv_timeout(struct connectdata *conn,
/* Ignore the timeout when signals are disabled */
timeout = 0;
else
- timeout = timeoutms;
+ timeout = (timeoutms > LONG_MAX) ? LONG_MAX : (long)timeoutms;
if(!timeout)
/* USE_ALARM_TIMEOUT defined, but no timeout actually requested */
@@ -689,10 +688,11 @@ clean_up:
the time we spent until now! */
if(prev_alarm) {
/* there was an alarm() set before us, now put it back */
- unsigned long elapsed_ms = Curl_tvdiff(Curl_tvnow(), conn->created);
+ unsigned long elapsed_secs = (unsigned long) (Curl_tvdiff(Curl_tvnow(),
+ conn->created) / 1000);
/* the alarm period is counted in even number of seconds */
- unsigned long alarm_set = prev_alarm - elapsed_ms/1000;
+ unsigned long alarm_set = prev_alarm - elapsed_secs;
if(!alarm_set ||
((alarm_set >= 0x80000000) && (prev_alarm < 0x80000000)) ) {
diff --git a/Utilities/cmcurl/lib/http.c b/Utilities/cmcurl/lib/http.c
index 22d4547097..21574e21d7 100644
--- a/Utilities/cmcurl/lib/http.c
+++ b/Utilities/cmcurl/lib/http.c
@@ -285,6 +285,7 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
const char *user;
const char *pwd;
CURLcode result;
+ char *out;
if(proxy) {
userp = &conn->allocptr.proxyuserpwd;
@@ -297,27 +298,32 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
pwd = conn->passwd;
}
- snprintf(data->state.buffer, CURL_BUFSIZE(data->set.buffer_size),
- "%s:%s", user, pwd);
+ out = aprintf("%s:%s", user, pwd);
+ if(!out)
+ return CURLE_OUT_OF_MEMORY;
- result = Curl_base64_encode(data,
- data->state.buffer, strlen(data->state.buffer),
- &authorization, &size);
+ result = Curl_base64_encode(data, out, strlen(out), &authorization, &size);
if(result)
- return result;
+ goto fail;
- if(!authorization)
- return CURLE_REMOTE_ACCESS_DENIED;
+ if(!authorization) {
+ result = CURLE_REMOTE_ACCESS_DENIED;
+ goto fail;
+ }
free(*userp);
*userp = aprintf("%sAuthorization: Basic %s\r\n",
proxy ? "Proxy-" : "",
authorization);
free(authorization);
- if(!*userp)
- return CURLE_OUT_OF_MEMORY;
+ if(!*userp) {
+ result = CURLE_OUT_OF_MEMORY;
+ goto fail;
+ }
- return CURLE_OK;
+ fail:
+ free(out);
+ return result;
}
/* pickoneauth() selects the most favourable authentication method from the
@@ -413,8 +419,6 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
case HTTPREQ_POST:
if(data->state.infilesize != -1)
expectsend = data->state.infilesize;
- else if(data->set.postfields)
- expectsend = (curl_off_t)strlen(data->set.postfields);
break;
case HTTPREQ_PUT:
if(data->state.infilesize != -1)
@@ -1111,7 +1115,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
buffer is using this size.
*/
- sendsize = (size > CURL_MAX_WRITE_SIZE) ? CURL_MAX_WRITE_SIZE : size;
+ sendsize = CURLMIN(size, CURL_MAX_WRITE_SIZE);
/* OpenSSL is very picky and we must send the SAME buffer pointer to the
library when we attempt to re-send this buffer. Sending the same data
@@ -1689,9 +1693,10 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
Curl_send_buffer *req_buffer)
{
const struct tm *tm;
- char *buf = data->state.buffer;
struct tm keeptime;
CURLcode result;
+ char datestr[80];
+ const char *condp;
if(data->set.timecondition == CURL_TIMECOND_NONE)
/* no condition was asked for */
@@ -1704,6 +1709,21 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
}
tm = &keeptime;
+ switch(data->set.timecondition) {
+ default:
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ case CURL_TIMECOND_IFMODSINCE:
+ condp = "If-Modified-Since";
+ break;
+ case CURL_TIMECOND_IFUNMODSINCE:
+ condp = "If-Unmodified-Since";
+ break;
+ case CURL_TIMECOND_LASTMOD:
+ condp = "Last-Modified";
+ break;
+ }
+
/* The If-Modified-Since header family should have their times set in
* GMT as RFC2616 defines: "All HTTP date/time stamps MUST be
* represented in Greenwich Mean Time (GMT), without exception. For the
@@ -1712,8 +1732,9 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
*/
/* format: "Tue, 15 Nov 1994 12:45:26 GMT" */
- snprintf(buf, BUFSIZE-1,
- "%s, %02d %s %4d %02d:%02d:%02d GMT",
+ snprintf(datestr, sizeof(datestr),
+ "%s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
+ condp,
Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
tm->tm_mday,
Curl_month[tm->tm_mon],
@@ -1722,22 +1743,7 @@ CURLcode Curl_add_timecondition(struct Curl_easy *data,
tm->tm_min,
tm->tm_sec);
- switch(data->set.timecondition) {
- default:
- break;
- case CURL_TIMECOND_IFMODSINCE:
- result = Curl_add_bufferf(req_buffer,
- "If-Modified-Since: %s\r\n", buf);
- break;
- case CURL_TIMECOND_IFUNMODSINCE:
- result = Curl_add_bufferf(req_buffer,
- "If-Unmodified-Since: %s\r\n", buf);
- break;
- case CURL_TIMECOND_LASTMOD:
- result = Curl_add_bufferf(req_buffer,
- "Last-Modified: %s\r\n", buf);
- break;
- }
+ result = Curl_add_buffer(req_buffer, datestr, strlen(datestr));
return result;
}
@@ -2164,8 +2170,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* when seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
do {
size_t readthisamountnow =
- (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
- BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
+ (data->state.resume_from - passed > data->set.buffer_size) ?
+ (size_t)data->set.buffer_size :
+ curlx_sotouz(data->state.resume_from - passed);
size_t actuallyread =
data->state.fread_func(data->state.buffer, 1, readthisamountnow,
@@ -2550,12 +2557,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(conn->bits.authneg)
postsize = 0;
- else {
- /* figure out the size of the postfields */
- postsize = (data->state.infilesize != -1)?
- data->state.infilesize:
- (data->set.postfields? (curl_off_t)strlen(data->set.postfields):-1);
- }
+ else
+ /* the size of the post body */
+ postsize = data->state.infilesize;
/* We only set Content-Length and allow a custom Content-Length if
we don't upload data chunked, as RFC2616 forbids us to set both
@@ -2737,6 +2741,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
data->req.upload_done = TRUE;
data->req.keepon &= ~KEEP_SEND; /* we're done writing */
data->req.exp100 = EXP100_SEND_DATA; /* already sent */
+ Curl_expire_done(data, EXPIRE_100_TIMEOUT);
}
}
@@ -3033,6 +3038,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
if(k->exp100 > EXP100_SEND_DATA) {
k->exp100 = EXP100_SEND_DATA;
k->keepon |= KEEP_SEND;
+ Curl_expire_done(data, EXPIRE_100_TIMEOUT);
}
break;
case 101:
@@ -3159,6 +3165,7 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
* request body has been sent we stop sending and mark the
* connection for closure after we've read the entire response.
*/
+ Curl_expire_done(data, EXPIRE_100_TIMEOUT);
if(!k->upload_done) {
if(data->set.http_keep_sending_on_error) {
infof(data, "HTTP error before end of send, keep sending\n");
diff --git a/Utilities/cmcurl/lib/http2.c b/Utilities/cmcurl/lib/http2.c
index 264c66700e..f8e23c517d 100644
--- a/Utilities/cmcurl/lib/http2.c
+++ b/Utilities/cmcurl/lib/http2.c
@@ -165,7 +165,7 @@ void Curl_http2_setup_req(struct Curl_easy *data)
http->closed = FALSE;
http->close_handled = FALSE;
http->mem = data->state.buffer;
- http->len = BUFSIZE;
+ http->len = data->set.buffer_size;
http->memlen = 0;
}
@@ -181,7 +181,7 @@ void Curl_http2_setup_conn(struct connectdata *conn)
* but will be used at run-time when the protocol is dynamically switched from
* HTTP to HTTP2.
*/
-const struct Curl_handler Curl_handler_http2 = {
+static const struct Curl_handler Curl_handler_http2 = {
"HTTP", /* scheme */
ZERO_NULL, /* setup_connection */
Curl_http, /* do_it */
@@ -201,7 +201,7 @@ const struct Curl_handler Curl_handler_http2 = {
PROTOPT_STREAM /* flags */
};
-const struct Curl_handler Curl_handler_http2_ssl = {
+static const struct Curl_handler Curl_handler_http2_ssl = {
"HTTPS", /* scheme */
ZERO_NULL, /* setup_connection */
Curl_http, /* do_it */
@@ -569,7 +569,7 @@ static int on_frame_recv(nghttp2_session *session, const nghttp2_frame *frame,
/* if we receive data for another handle, wake that up */
if(conn_s->data != data_s)
- Curl_expire(data_s, 0);
+ Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
}
break;
case NGHTTP2_PUSH_PROMISE:
@@ -646,7 +646,7 @@ static int on_data_chunk_recv(nghttp2_session *session, uint8_t flags,
/* if we receive data for another handle, wake that up */
if(conn->data != data_s)
- Curl_expire(data_s, 0);
+ Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
DEBUGF(infof(data_s, "%zu data received for stream %u "
"(%zu left in buffer %p, total %zu)\n",
@@ -784,7 +784,7 @@ static int on_begin_headers(nghttp2_session *session,
/* This is trailer HEADERS started. Allocate buffer for them. */
DEBUGF(infof(data_s, "trailer field started\n"));
- assert(stream->trailer_recvbuf == NULL);
+ DEBUGASSERT(stream->trailer_recvbuf == NULL);
stream->trailer_recvbuf = Curl_add_buffer_init();
if(!stream->trailer_recvbuf) {
@@ -909,7 +909,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
Curl_add_buffer(stream->header_recvbuf, " \r\n", 3);
/* if we receive data for another handle, wake that up */
if(conn->data != data_s)
- Curl_expire(data_s, 0);
+ Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
DEBUGF(infof(data_s, "h2 status: HTTP/2 %03d (easy %p)\n",
stream->status_code, data_s));
@@ -925,7 +925,7 @@ static int on_header(nghttp2_session *session, const nghttp2_frame *frame,
Curl_add_buffer(stream->header_recvbuf, "\r\n", 2);
/* if we receive data for another handle, wake that up */
if(conn->data != data_s)
- Curl_expire(data_s, 0);
+ Curl_expire(data_s, 0, EXPIRE_RUN_NOW);
DEBUGF(infof(data_s, "h2 header: %.*s: %.*s\n", namelen, name, valuelen,
value));
@@ -1453,7 +1453,7 @@ static ssize_t http2_recv(struct connectdata *conn, int sockindex,
infof(data, "%zu data bytes written\n", nread);
if(stream->pauselen == 0) {
DEBUGF(infof(data, "Unpaused by stream %u\n", stream->stream_id));
- assert(httpc->pause_stream_id == stream->stream_id);
+ DEBUGASSERT(httpc->pause_stream_id == stream->stream_id);
httpc->pause_stream_id = 0;
stream->pausedata = NULL;
@@ -2137,35 +2137,37 @@ CURLcode Curl_http2_switched(struct connectdata *conn,
void Curl_http2_add_child(struct Curl_easy *parent, struct Curl_easy *child,
bool exclusive)
{
- struct Curl_http2_dep **tail;
- struct Curl_http2_dep *dep = calloc(1, sizeof(struct Curl_http2_dep));
- dep->data = child;
-
- if(parent->set.stream_dependents && exclusive) {
- struct Curl_http2_dep *node = parent->set.stream_dependents;
- while(node) {
- node->data->set.stream_depends_on = child;
- node = node->next;
+ if(parent) {
+ struct Curl_http2_dep **tail;
+ struct Curl_http2_dep *dep = calloc(1, sizeof(struct Curl_http2_dep));
+ dep->data = child;
+
+ if(parent->set.stream_dependents && exclusive) {
+ struct Curl_http2_dep *node = parent->set.stream_dependents;
+ while(node) {
+ node->data->set.stream_depends_on = child;
+ node = node->next;
+ }
+
+ tail = &child->set.stream_dependents;
+ while(*tail)
+ tail = &(*tail)->next;
+
+ DEBUGASSERT(!*tail);
+ *tail = parent->set.stream_dependents;
+ parent->set.stream_dependents = 0;
}
- tail = &child->set.stream_dependents;
- while(*tail)
+ tail = &parent->set.stream_dependents;
+ while(*tail) {
+ (*tail)->data->set.stream_depends_e = FALSE;
tail = &(*tail)->next;
+ }
DEBUGASSERT(!*tail);
- *tail = parent->set.stream_dependents;
- parent->set.stream_dependents = 0;
+ *tail = dep;
}
- tail = &parent->set.stream_dependents;
- while(*tail) {
- (*tail)->data->set.stream_depends_e = FALSE;
- tail = &(*tail)->next;
- }
-
- DEBUGASSERT(!*tail);
- *tail = dep;
-
child->set.stream_depends_on = parent;
child->set.stream_depends_e = exclusive;
}
diff --git a/Utilities/cmcurl/lib/http_proxy.c b/Utilities/cmcurl/lib/http_proxy.c
index d53685f53e..9894e2e5ff 100644
--- a/Utilities/cmcurl/lib/http_proxy.c
+++ b/Utilities/cmcurl/lib/http_proxy.c
@@ -122,8 +122,7 @@ CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
remote_port = conn->conn_to_port;
else
remote_port = conn->remote_port;
- result = Curl_proxyCONNECT(conn, sockindex, hostname,
- remote_port, FALSE);
+ result = Curl_proxyCONNECT(conn, sockindex, hostname, remote_port);
conn->data->req.protop = prot_save;
if(CURLE_OK != result)
return result;
@@ -136,20 +135,12 @@ CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex)
return CURLE_OK;
}
-/*
- * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This
- * function will issue the necessary commands to get a seamless tunnel through
- * this proxy. After that, the socket can be used just as a normal socket.
- *
- * 'blocking' set to TRUE means that this function will do the entire CONNECT
- * + response in a blocking fashion. Should be avoided!
- */
+#define CONNECT_BUFFER_SIZE 16384
-CURLcode Curl_proxyCONNECT(struct connectdata *conn,
- int sockindex,
- const char *hostname,
- int remote_port,
- bool blocking)
+static CURLcode CONNECT(struct connectdata *conn,
+ int sockindex,
+ const char *hostname,
+ int remote_port)
{
int subversion=0;
struct Curl_easy *data=conn->data;
@@ -289,13 +280,10 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
return CURLE_RECV_ERROR;
}
- if(!blocking) {
- if(!Curl_conn_data_pending(conn, sockindex))
- /* return so we'll be called again polling-style */
- return CURLE_OK;
- DEBUGF(infof(data,
- "Read response immediately from proxy CONNECT\n"));
- }
+ if(!Curl_conn_data_pending(conn, sockindex))
+ /* return so we'll be called again polling-style */
+ return CURLE_OK;
+ DEBUGF(infof(data, "Read response immediately from proxy CONNECT\n"));
/* at this point, the tunnel_connecting phase is over. */
@@ -307,17 +295,17 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
char *ptr;
char *line_start;
- ptr = data->state.buffer;
+ ptr = conn->connect_buffer;
line_start = ptr;
nread = 0;
perline = 0;
- while(nread < BUFSIZE && keepon && !error) {
+ while(nread < (size_t)CONNECT_BUFFER_SIZE && keepon && !error) {
if(Curl_pgrsUpdate(conn))
return CURLE_ABORTED_BY_CALLBACK;
- if(ptr >= &data->state.buffer[BUFSIZE]) {
+ if(ptr >= &conn->connect_buffer[CONNECT_BUFFER_SIZE]) {
failf(data, "CONNECT response too large!");
return CURLE_RECV_ERROR;
}
@@ -366,7 +354,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
/* This means we are currently ignoring a response-body */
nread = 0; /* make next read start over in the read buffer */
- ptr = data->state.buffer;
+ ptr = conn->connect_buffer;
if(cl) {
/* A Content-Length based body: simply count down the counter
and make sure to break out of the loop when we're done! */
@@ -438,7 +426,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
/* end of response-headers from the proxy */
nread = 0; /* make next read start over in the read
buffer */
- ptr = data->state.buffer;
+ ptr = conn->connect_buffer;
if((407 == k->httpcode) && !data->state.authproblem) {
/* If we get a 407 response code with content length
when we have no auth problem, we must ignore the
@@ -551,7 +539,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
}
perline = 0; /* line starts over here */
- ptr = data->state.buffer;
+ ptr = conn->connect_buffer;
line_start = ptr;
} /* while there's buffer left and loop is requested */
@@ -636,4 +624,33 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
document request */
return CURLE_OK;
}
+
+/*
+ * Curl_proxyCONNECT() requires that we're connected to a HTTP proxy. This
+ * function will issue the necessary commands to get a seamless tunnel through
+ * this proxy. After that, the socket can be used just as a normal socket.
+ */
+
+CURLcode Curl_proxyCONNECT(struct connectdata *conn,
+ int sockindex,
+ const char *hostname,
+ int remote_port)
+{
+ CURLcode result;
+ if(TUNNEL_INIT == conn->tunnel_state[sockindex]) {
+ if(!conn->connect_buffer) {
+ conn->connect_buffer = malloc(CONNECT_BUFFER_SIZE);
+ if(!conn->connect_buffer)
+ return CURLE_OUT_OF_MEMORY;
+ }
+ }
+ result = CONNECT(conn, sockindex, hostname, remote_port);
+
+ if(result || (TUNNEL_COMPLETE == conn->tunnel_state[sockindex]))
+ Curl_safefree(conn->connect_buffer);
+
+ return result;
+}
+
+
#endif /* CURL_DISABLE_PROXY */
diff --git a/Utilities/cmcurl/lib/http_proxy.h b/Utilities/cmcurl/lib/http_proxy.h
index d1f5a7c83f..cbb1ab4212 100644
--- a/Utilities/cmcurl/lib/http_proxy.h
+++ b/Utilities/cmcurl/lib/http_proxy.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -26,8 +26,7 @@
/* ftp can use this as well */
CURLcode Curl_proxyCONNECT(struct connectdata *conn,
int tunnelsocket,
- const char *hostname, int remote_port,
- bool blocking);
+ const char *hostname, int remote_port);
/* Default proxy timeout in milliseconds */
#define PROXY_TIMEOUT (3600*1000)
@@ -35,7 +34,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
CURLcode Curl_proxy_connect(struct connectdata *conn, int sockindex);
#else
-#define Curl_proxyCONNECT(x,y,z,w,v) CURLE_NOT_BUILT_IN
+#define Curl_proxyCONNECT(x,y,z,w) CURLE_NOT_BUILT_IN
#define Curl_proxy_connect(x,y) CURLE_OK
#endif
diff --git a/Utilities/cmcurl/lib/if2ip.c b/Utilities/cmcurl/lib/if2ip.c
index d876615ea1..4de81be60e 100644
--- a/Utilities/cmcurl/lib/if2ip.c
+++ b/Utilities/cmcurl/lib/if2ip.c
@@ -239,7 +239,7 @@ if2ip_result_t Curl_if2ip(int af, unsigned int remote_scope,
return IF2IP_NOT_FOUND;
}
- s = (struct sockaddr_in *)&req.ifr_addr;
+ s = (struct sockaddr_in *)(void *)&req.ifr_addr;
memcpy(&in, &s->sin_addr, sizeof(in));
Curl_inet_ntop(s->sin_family, &in, buf, buf_size);
diff --git a/Utilities/cmcurl/lib/krb5.c b/Utilities/cmcurl/lib/krb5.c
index 067b0a5778..69a35979a8 100644
--- a/Utilities/cmcurl/lib/krb5.c
+++ b/Utilities/cmcurl/lib/krb5.c
@@ -164,6 +164,7 @@ krb5_auth(void *app_data, struct connectdata *conn)
size_t base64_sz = 0;
struct sockaddr_in **remote_addr =
(struct sockaddr_in **)&conn->ip_addr->ai_addr;
+ char *stringp;
if(getsockname(conn->sock[FIRSTSOCKET],
(struct sockaddr *)&conn->local_addr, &l) < 0)
@@ -193,16 +194,19 @@ krb5_auth(void *app_data, struct connectdata *conn)
return -1;
}
- input_buffer.value = data->state.buffer;
- input_buffer.length = snprintf(input_buffer.value, BUFSIZE, "%s@%s",
- service, host);
+ stringp = aprintf("%s@%s", service, host);
+ if(!stringp)
+ return -2;
+
+ input_buffer.value = stringp;
+ input_buffer.length = strlen(stringp);
maj = gss_import_name(&min, &input_buffer, GSS_C_NT_HOSTBASED_SERVICE,
&gssname);
+ free(stringp);
if(maj != GSS_S_COMPLETE) {
gss_release_name(&min, &gssname);
if(service == srv_host) {
- Curl_failf(data, "Error importing service name %s",
- input_buffer.value);
+ Curl_failf(data, "Error importing service name %s@%s", service, host);
return AUTH_ERROR;
}
service = srv_host;
diff --git a/Utilities/cmcurl/lib/ldap.c b/Utilities/cmcurl/lib/ldap.c
index 979ce7de43..79e84d94e5 100644
--- a/Utilities/cmcurl/lib/ldap.c
+++ b/Utilities/cmcurl/lib/ldap.c
@@ -181,6 +181,81 @@ const struct Curl_handler Curl_handler_ldaps = {
};
#endif
+#if defined(USE_WIN32_LDAP)
+
+#if defined(USE_WINDOWS_SSPI)
+static int ldap_win_bind_auth(LDAP *server, const char *user,
+ const char *passwd, unsigned long authflags)
+{
+ ULONG method = 0;
+ SEC_WINNT_AUTH_IDENTITY cred = { 0, };
+ int rc = LDAP_AUTH_METHOD_NOT_SUPPORTED;
+
+#if defined(USE_SPNEGO)
+ if(authflags & CURLAUTH_NEGOTIATE) {
+ method = LDAP_AUTH_NEGOTIATE;
+ }
+ else
+#endif
+#if defined(USE_NTLM)
+ if(authflags & CURLAUTH_NTLM) {
+ method = LDAP_AUTH_NTLM;
+ }
+ else
+#endif
+#if !defined(CURL_DISABLE_CRYPTO_AUTH)
+ if(authflags & CURLAUTH_DIGEST) {
+ method = LDAP_AUTH_DIGEST;
+ }
+ else
+#endif
+ {
+ /* required anyway if one of upper preprocessor definitions enabled */
+ }
+
+ if(method && user && passwd) {
+ rc = Curl_create_sspi_identity(user, passwd, &cred);
+ if(!rc) {
+ rc = ldap_bind_s(server, NULL, (TCHAR *)&cred, method);
+ Curl_sspi_free_identity(&cred);
+ }
+ }
+ else {
+ /* proceed with current user credentials */
+ method = LDAP_AUTH_NEGOTIATE;
+ rc = ldap_bind_s(server, NULL, NULL, method);
+ }
+ return rc;
+}
+#endif /* #if defined(USE_WINDOWS_SSPI) */
+
+static int ldap_win_bind(struct connectdata *conn, LDAP *server,
+ const char *user, const char *passwd)
+{
+ int rc = LDAP_INVALID_CREDENTIALS;
+ ULONG method = LDAP_AUTH_SIMPLE;
+
+ PTCHAR inuser = NULL;
+ PTCHAR inpass = NULL;
+
+ if(user && passwd && (conn->data->set.httpauth & CURLAUTH_BASIC)) {
+ inuser = Curl_convert_UTF8_to_tchar((char *) user);
+ inpass = Curl_convert_UTF8_to_tchar((char *) passwd);
+
+ rc = ldap_bind_s(server, inuser, inpass, method);
+
+ Curl_unicodefree(inuser);
+ Curl_unicodefree(inpass);
+ }
+#if defined(USE_WINDOWS_SSPI)
+ else {
+ rc = ldap_win_bind_auth(server, user, passwd, conn->data->set.httpauth);
+ }
+#endif
+
+ return rc;
+}
+#endif /* #if defined(USE_WIN32_LDAP) */
static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
{
@@ -202,13 +277,11 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
#endif
#if defined(USE_WIN32_LDAP)
TCHAR *host = NULL;
- TCHAR *user = NULL;
- TCHAR *passwd = NULL;
#else
char *host = NULL;
+#endif
char *user = NULL;
char *passwd = NULL;
-#endif
*done = TRUE; /* unconditionally */
infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d\n",
@@ -239,24 +312,14 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
goto quit;
}
-
- if(conn->bits.user_passwd) {
- user = Curl_convert_UTF8_to_tchar(conn->user);
- passwd = Curl_convert_UTF8_to_tchar(conn->passwd);
- if(!user || !passwd) {
- result = CURLE_OUT_OF_MEMORY;
-
- goto quit;
- }
- }
#else
host = conn->host.name;
+#endif
if(conn->bits.user_passwd) {
user = conn->user;
passwd = conn->passwd;
}
-#endif
#ifdef LDAP_OPT_NETWORK_TIMEOUT
ldap_set_option(NULL, LDAP_OPT_NETWORK_TIMEOUT, &ldap_timeout);
@@ -402,11 +465,19 @@ static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
#endif
+#ifdef USE_WIN32_LDAP
+ rc = ldap_win_bind(conn, server, user, passwd);
+#else
rc = ldap_simple_bind_s(server, user, passwd);
+#endif
if(!ldap_ssl && rc != 0) {
ldap_proto = LDAP_VERSION2;
ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
+#ifdef USE_WIN32_LDAP
+ rc = ldap_win_bind(conn, server, user, passwd);
+#else
rc = ldap_simple_bind_s(server, user, passwd);
+#endif
}
if(rc != 0) {
failf(data, "LDAP local: ldap_simple_bind_s %s", ldap_err2string(rc));
@@ -669,8 +740,6 @@ quit:
#endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */
#if defined(USE_WIN32_LDAP)
- Curl_unicodefree(passwd);
- Curl_unicodefree(user);
Curl_unicodefree(host);
#endif
diff --git a/Utilities/cmcurl/lib/llist.c b/Utilities/cmcurl/lib/llist.c
index b8836bbccf..4bb0a51b86 100644
--- a/Utilities/cmcurl/lib/llist.c
+++ b/Utilities/cmcurl/lib/llist.c
@@ -49,18 +49,15 @@ Curl_llist_init(struct curl_llist *l, curl_llist_dtor dtor)
* entry is NULL and the list already has elements, the new one will be
* inserted first in the list.
*
- * Returns: 1 on success and 0 on failure.
+ * The 'ne' argument should be a pointer into the object to store.
*
* @unittest: 1300
*/
-int
+void
Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e,
- const void *p)
+ const void *p,
+ struct curl_llist_element *ne)
{
- struct curl_llist_element *ne = malloc(sizeof(struct curl_llist_element));
- if(!ne)
- return 0;
-
ne->ptr = (void *) p;
if(list->size == 0) {
list->head = ne;
@@ -87,19 +84,18 @@ Curl_llist_insert_next(struct curl_llist *list, struct curl_llist_element *e,
}
++list->size;
-
- return 1;
}
/*
* @unittest: 1300
*/
-int
+void
Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e,
void *user)
{
+ void *ptr;
if(e == NULL || list->size == 0)
- return 1;
+ return;
if(e == list->head) {
list->head = e->next;
@@ -117,16 +113,17 @@ Curl_llist_remove(struct curl_llist *list, struct curl_llist_element *e,
e->next->prev = e->prev;
}
- list->dtor(user, e->ptr);
+ ptr = e->ptr;
e->ptr = NULL;
e->prev = NULL;
e->next = NULL;
- free(e);
--list->size;
- return 1;
+ /* call the dtor() last for when it actually frees the 'e' memory itself */
+ if(list->dtor)
+ list->dtor(user, ptr);
}
void
@@ -147,13 +144,13 @@ Curl_llist_count(struct curl_llist *list)
/*
* @unittest: 1300
*/
-int Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e,
- struct curl_llist *to_list,
- struct curl_llist_element *to_e)
+void Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e,
+ struct curl_llist *to_list,
+ struct curl_llist_element *to_e)
{
/* Remove element from list */
if(e == NULL || list->size == 0)
- return 0;
+ return;
if(e == list->head) {
list->head = e->next;
@@ -193,6 +190,4 @@ int Curl_llist_move(struct curl_llist *list, struct curl_llist_element *e,
}
++to_list->size;
-
- return 1;
}
diff --git a/Utilities/cmcurl/lib/llist.h b/Utilities/cmcurl/lib/llist.h
index 47935ad1f5..6b644b99c8 100644
--- a/Utilities/cmcurl/lib/llist.h
+++ b/Utilities/cmcurl/lib/llist.h
@@ -29,7 +29,6 @@ typedef void (*curl_llist_dtor)(void *, void *);
struct curl_llist_element {
void *ptr;
-
struct curl_llist_element *prev;
struct curl_llist_element *next;
};
@@ -37,21 +36,19 @@ struct curl_llist_element {
struct curl_llist {
struct curl_llist_element *head;
struct curl_llist_element *tail;
-
curl_llist_dtor dtor;
-
size_t size;
};
void Curl_llist_init(struct curl_llist *, curl_llist_dtor);
-int Curl_llist_insert_next(struct curl_llist *, struct curl_llist_element *,
- const void *);
-int Curl_llist_remove(struct curl_llist *, struct curl_llist_element *,
- void *);
+void Curl_llist_insert_next(struct curl_llist *, struct curl_llist_element *,
+ const void *, struct curl_llist_element *node);
+void Curl_llist_remove(struct curl_llist *, struct curl_llist_element *,
+ void *);
size_t Curl_llist_count(struct curl_llist *);
void Curl_llist_destroy(struct curl_llist *, void *);
-int Curl_llist_move(struct curl_llist *, struct curl_llist_element *,
- struct curl_llist *, struct curl_llist_element *);
+void Curl_llist_move(struct curl_llist *, struct curl_llist_element *,
+ struct curl_llist *, struct curl_llist_element *);
#endif /* HEADER_CURL_LLIST_H */
diff --git a/Utilities/cmcurl/lib/md4.c b/Utilities/cmcurl/lib/md4.c
index 1bdc9f367c..2bb7dcc25a 100644
--- a/Utilities/cmcurl/lib/md4.c
+++ b/Utilities/cmcurl/lib/md4.c
@@ -37,9 +37,10 @@
#include "curl_setup.h"
-/* NSS and OS/400 crypto library do not provide the MD4 hash algorithm, so
- * that we have a local implementation of it */
-#if defined(USE_NSS) || defined(USE_OS400CRYPTO)
+/* The NSS, OS/400 and sometimes mbed TLS crypto libraries do not provide the
+ * MD4 hash algorithm, so we have a local implementation of it */
+#if defined(USE_NSS) || defined(USE_OS400CRYPTO) || \
+ (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C))
#include "curl_md4.h"
#include "warnless.h"
@@ -89,7 +90,7 @@ static void MD4_Final(unsigned char *result, MD4_CTX *ctx);
*/
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
#define SET(n) \
- (*(MD4_u32plus *)&ptr[(n) * 4])
+ (*(MD4_u32plus *)(void *)&ptr[(n) * 4])
#define GET(n) \
SET(n)
#else
@@ -302,4 +303,5 @@ void Curl_md4it(unsigned char *output, const unsigned char *input, size_t len)
MD4_Update(&ctx, input, curlx_uztoui(len));
MD4_Final(output, &ctx);
}
-#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) */
+#endif /* defined(USE_NSS) || defined(USE_OS400CRYPTO) ||
+ (defined(USE_MBEDTLS) && !defined(MBEDTLS_MD4_C)) */
diff --git a/Utilities/cmcurl/lib/md5.c b/Utilities/cmcurl/lib/md5.c
index f2dc16c099..80301a1412 100644
--- a/Utilities/cmcurl/lib/md5.c
+++ b/Utilities/cmcurl/lib/md5.c
@@ -260,7 +260,7 @@ static void MD5_Final(unsigned char *result, MD5_CTX *ctx);
*/
#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
#define SET(n) \
- (*(MD5_u32plus *)&ptr[(n) * 4])
+ (*(MD5_u32plus *)(void *)&ptr[(n) * 4])
#define GET(n) \
SET(n)
#else
diff --git a/Utilities/cmcurl/lib/memdebug.c b/Utilities/cmcurl/lib/memdebug.c
index 32d2adfb5b..2b8808ab03 100644
--- a/Utilities/cmcurl/lib/memdebug.c
+++ b/Utilities/cmcurl/lib/memdebug.c
@@ -35,10 +35,6 @@
#include "curl_memory.h"
#include "memdebug.h"
-#ifndef HAVE_ASSERT_H
-# define assert(x) Curl_nop_stmt
-#endif
-
/*
* Until 2011-08-17 libcurl's Memory Tracking feature also performed
* automatic malloc and free filling operations using 0xA5 and 0x13
@@ -167,7 +163,7 @@ void *curl_domalloc(size_t wantedsize, int line, const char *source)
struct memdebug *mem;
size_t size;
- assert(wantedsize != 0);
+ DEBUGASSERT(wantedsize != 0);
if(countcheck("malloc", line, source))
return NULL;
@@ -196,8 +192,8 @@ void *curl_docalloc(size_t wanted_elements, size_t wanted_size,
struct memdebug *mem;
size_t size, user_size;
- assert(wanted_elements != 0);
- assert(wanted_size != 0);
+ DEBUGASSERT(wanted_elements != 0);
+ DEBUGASSERT(wanted_size != 0);
if(countcheck("calloc", line, source))
return NULL;
@@ -223,7 +219,7 @@ char *curl_dostrdup(const char *str, int line, const char *source)
char *mem;
size_t len;
- assert(str != NULL);
+ DEBUGASSERT(str != NULL);
if(countcheck("strdup", line, source))
return NULL;
@@ -236,7 +232,7 @@ char *curl_dostrdup(const char *str, int line, const char *source)
if(source)
curl_memlog("MEM %s:%d strdup(%p) (%zu) = %p\n",
- source, line, (void *)str, len, (void *)mem);
+ source, line, (const void *)str, len, (const void *)mem);
return mem;
}
@@ -247,7 +243,7 @@ wchar_t *curl_dowcsdup(const wchar_t *str, int line, const char *source)
wchar_t *mem;
size_t wsiz, bsiz;
- assert(str != NULL);
+ DEBUGASSERT(str != NULL);
if(countcheck("wcsdup", line, source))
return NULL;
@@ -276,7 +272,7 @@ void *curl_dorealloc(void *ptr, size_t wantedsize,
size_t size = sizeof(struct memdebug)+wantedsize;
- assert(wantedsize != 0);
+ DEBUGASSERT(wantedsize != 0);
if(countcheck("realloc", line, source))
return NULL;
@@ -445,7 +441,7 @@ int curl_fclose(FILE *file, int line, const char *source)
{
int res;
- assert(file != NULL);
+ DEBUGASSERT(file != NULL);
res=fclose(file);
@@ -480,7 +476,7 @@ void curl_memlog(const char *format, ...)
nchars = LOGLINE_BUFSIZE - 1;
if(nchars > 0)
- fwrite(buf, 1, nchars, logfile);
+ fwrite(buf, 1, (size_t)nchars, logfile);
(Curl_cfree)(buf);
}
diff --git a/Utilities/cmcurl/lib/mprintf.c b/Utilities/cmcurl/lib/mprintf.c
index 6d4e733f0c..eb7ee0c6b0 100644
--- a/Utilities/cmcurl/lib/mprintf.c
+++ b/Utilities/cmcurl/lib/mprintf.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1999 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1999 - 2017, 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
@@ -610,7 +610,7 @@ static int dprintf_formatf(
int is_neg;
/* Base of a number to be written. */
- long base;
+ unsigned long base;
/* Integral values to be written. */
mp_uintmax_t num;
@@ -951,9 +951,7 @@ static int dprintf_formatf(
/* NOTE NOTE NOTE!! Not all sprintf implementations return number of
output characters */
(sprintf)(work, formatbuf, p->data.dnum);
-#ifdef CURLDEBUG
- assert(strlen(work) <= sizeof(work));
-#endif
+ DEBUGASSERT(strlen(work) <= sizeof(work));
for(fptr=work; *fptr; fptr++)
OUTCHAR(*fptr);
}
diff --git a/Utilities/cmcurl/lib/multi.c b/Utilities/cmcurl/lib/multi.c
index b24ce19ddf..c3a0d122cb 100644
--- a/Utilities/cmcurl/lib/multi.c
+++ b/Utilities/cmcurl/lib/multi.c
@@ -99,8 +99,6 @@ static const char * const statename[]={
};
#endif
-static void multi_freetimeout(void *a, void *b);
-
/* function pointer called once when switching TO a state */
typedef void (*init_multistate_func)(struct Curl_easy *data);
@@ -280,9 +278,8 @@ static int sh_init(struct curl_hash *hash, int hashsize)
static CURLMcode multi_addmsg(struct Curl_multi *multi,
struct Curl_message *msg)
{
- if(!Curl_llist_insert_next(&multi->msglist, multi->msglist.tail, msg))
- return CURLM_OUT_OF_MEMORY;
-
+ Curl_llist_insert_next(&multi->msglist, multi->msglist.tail, msg,
+ &msg->list);
return CURLM_OK;
}
@@ -370,7 +367,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
return CURLM_ADDED_ALREADY;
/* Initialize timeout list for this handle */
- Curl_llist_init(&data->state.timeoutlist, multi_freetimeout);
+ Curl_llist_init(&data->state.timeoutlist, NULL);
/*
* No failure allowed in this function beyond this point. And no
@@ -431,7 +428,7 @@ CURLMcode curl_multi_add_handle(struct Curl_multi *multi,
sockets that time-out or have actions will be dealt with. Since this
handle has no action yet, we make sure it times out to get things to
happen. */
- Curl_expire(data, 0);
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
/* increase the node-counter */
multi->num_easy++;
@@ -1015,7 +1012,7 @@ CURLMcode curl_multi_wait(struct Curl_multi *multi,
curlfds = nfds; /* number of internal file descriptors */
nfds += extra_nfds; /* add the externally provided ones */
- if(nfds || extra_nfds) {
+ if(nfds) {
if(nfds > NUM_POLLS_ON_STACK) {
ufds = malloc(nfds * sizeof(struct pollfd));
if(!ufds)
@@ -1432,10 +1429,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
multistate(data, CURLM_STATE_CONNECT_PEND);
/* add this handle to the list of connect-pending handles */
- if(!Curl_llist_insert_next(&multi->pending, multi->pending.tail, data))
- result = CURLE_OUT_OF_MEMORY;
- else
- result = CURLE_OK;
+ Curl_llist_insert_next(&multi->pending, multi->pending.tail, data,
+ &data->connect_queue);
+ result = CURLE_OK;
break;
}
@@ -1719,20 +1715,18 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
else {
/* Follow failed */
result = drc;
- free(newurl);
}
}
else {
/* done didn't return OK or SEND_ERROR */
result = drc;
- free(newurl);
}
}
else {
/* Have error handler disconnect conn if we can't retry */
stream_error = TRUE;
- free(newurl);
}
+ free(newurl);
}
else {
/* failure detected */
@@ -1846,9 +1840,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(send_timeout_ms <= 0 && recv_timeout_ms <= 0)
multistate(data, CURLM_STATE_PERFORM);
else if(send_timeout_ms >= recv_timeout_ms)
- Curl_expire_latest(data, send_timeout_ms);
+ Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
else
- Curl_expire_latest(data, recv_timeout_ms);
+ Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
}
break;
@@ -1879,9 +1873,9 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(send_timeout_ms > 0 || recv_timeout_ms > 0) {
multistate(data, CURLM_STATE_TOOFAST);
if(send_timeout_ms >= recv_timeout_ms)
- Curl_expire_latest(data, send_timeout_ms);
+ Curl_expire(data, send_timeout_ms, EXPIRE_TOOFAST);
else
- Curl_expire_latest(data, recv_timeout_ms);
+ Curl_expire(data, recv_timeout_ms, EXPIRE_TOOFAST);
break;
}
@@ -1942,7 +1936,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
/* expire the new receiving pipeline head */
if(data->easy_conn->recv_pipe.head)
- Curl_expire_latest(data->easy_conn->recv_pipe.head->ptr, 0);
+ Curl_expire(data->easy_conn->recv_pipe.head->ptr, 0, EXPIRE_RUN_NOW);
/* Check if we can move pending requests to send pipe */
Curl_multi_process_pending_handles(multi);
@@ -1966,9 +1960,6 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
if(!result) {
multistate(data, CURLM_STATE_CONNECT);
rc = CURLM_CALL_MULTI_PERFORM;
- newurl = NULL; /* handed over the memory ownership to
- Curl_follow(), make sure we don't free() it
- here */
}
}
}
@@ -1982,9 +1973,7 @@ static CURLMcode multi_runsingle(struct Curl_multi *multi,
newurl = data->req.location;
data->req.location = NULL;
result = Curl_follow(data, newurl, FOLLOW_FAKE);
- if(!result)
- newurl = NULL; /* allocation was handed over Curl_follow() */
- else
+ if(result)
stream_error = TRUE;
}
@@ -2483,8 +2472,6 @@ void Curl_multi_closed(struct connectdata *conn, curl_socket_t s)
}
}
-
-
/*
* add_next_timeout()
*
@@ -2504,13 +2491,16 @@ static CURLMcode add_next_timeout(struct timeval now,
struct timeval *tv = &d->state.expiretime;
struct curl_llist *list = &d->state.timeoutlist;
struct curl_llist_element *e;
+ struct time_node *node = NULL;
/* move over the timeout list for this specific handle and remove all
timeouts that are now passed tense and store the next pending
timeout in *tv */
for(e = list->head; e;) {
struct curl_llist_element *n = e->next;
- time_t diff = curlx_tvdiff(*(struct timeval *)e->ptr, now);
+ time_t diff;
+ node = (struct time_node *)e->ptr;
+ diff = curlx_tvdiff(node->time, now);
if(diff <= 0)
/* remove outdated entry */
Curl_llist_remove(list, e, NULL);
@@ -2528,7 +2518,7 @@ static CURLMcode add_next_timeout(struct timeval now,
}
else {
/* copy the first entry to 'tv' */
- memcpy(tv, e->ptr, sizeof(*tv));
+ memcpy(tv, &node->time, sizeof(*tv));
/* remove first entry from list */
Curl_llist_remove(list, e, NULL);
@@ -2854,17 +2844,23 @@ static int update_timer(struct Curl_multi *multi)
}
/*
- * multi_freetimeout()
+ * multi_deltimeout()
*
- * Callback used by the llist system when a single timeout list entry is
- * destroyed.
+ * Remove a given timestamp from the list of timeouts.
*/
-static void multi_freetimeout(void *user, void *entryptr)
+static void
+multi_deltimeout(struct Curl_easy *data, expire_id eid)
{
- (void)user;
-
- /* the entry was plain malloc()'ed */
- free(entryptr);
+ struct curl_llist_element *e;
+ struct curl_llist *timeoutlist = &data->state.timeoutlist;
+ /* find and remove the specific node from the list */
+ for(e = timeoutlist->head; e; e = e->next) {
+ struct time_node *n = (struct time_node *)e->ptr;
+ if(n->eid == eid) {
+ Curl_llist_remove(timeoutlist, e, NULL);
+ return;
+ }
+ }
}
/*
@@ -2875,25 +2871,28 @@ static void multi_freetimeout(void *user, void *entryptr)
*
*/
static CURLMcode
-multi_addtimeout(struct curl_llist *timeoutlist,
- struct timeval *stamp)
+multi_addtimeout(struct Curl_easy *data,
+ struct timeval *stamp,
+ expire_id eid)
{
struct curl_llist_element *e;
- struct timeval *timedup;
+ struct time_node *node;
struct curl_llist_element *prev = NULL;
+ size_t n;
+ struct curl_llist *timeoutlist = &data->state.timeoutlist;
- timedup = malloc(sizeof(*timedup));
- if(!timedup)
- return CURLM_OUT_OF_MEMORY;
+ node = &data->state.expires[eid];
- /* copy the timestamp */
- memcpy(timedup, stamp, sizeof(*timedup));
+ /* copy the timestamp and id */
+ memcpy(&node->time, stamp, sizeof(*stamp));
+ node->eid = eid; /* also marks it as in use */
- if(Curl_llist_count(timeoutlist)) {
+ n = Curl_llist_count(timeoutlist);
+ if(n) {
/* find the correct spot in the list */
for(e = timeoutlist->head; e; e = e->next) {
- struct timeval *checktime = e->ptr;
- time_t diff = curlx_tvdiff(*checktime, *timedup);
+ struct time_node *check = (struct time_node *)e->ptr;
+ time_t diff = curlx_tvdiff(check->time, node->time);
if(diff > 0)
break;
prev = e;
@@ -2903,11 +2902,7 @@ multi_addtimeout(struct curl_llist *timeoutlist,
/* else
this is the first timeout on the list */
- if(!Curl_llist_insert_next(timeoutlist, prev, timedup)) {
- free(timedup);
- return CURLM_OUT_OF_MEMORY;
- }
-
+ Curl_llist_insert_next(timeoutlist, prev, node, &node->list);
return CURLM_OK;
}
@@ -2919,8 +2914,10 @@ multi_addtimeout(struct curl_llist *timeoutlist,
*
* The timeout will be added to a queue of timeouts if it defines a moment in
* time that is later than the current head of queue.
+ *
+ * Expire replaces a former timeout using the same id if already set.
*/
-void Curl_expire(struct Curl_easy *data, time_t milli)
+void Curl_expire(struct Curl_easy *data, time_t milli, expire_id id)
{
struct Curl_multi *multi = data->multi;
struct timeval *nowp = &data->state.expiretime;
@@ -2932,6 +2929,8 @@ void Curl_expire(struct Curl_easy *data, time_t milli)
if(!multi)
return;
+ DEBUGASSERT(id < EXPIRE_LAST);
+
set = Curl_tvnow();
set.tv_sec += (long)(milli/1000);
set.tv_usec += (long)(milli%1000)*1000;
@@ -2946,16 +2945,20 @@ void Curl_expire(struct Curl_easy *data, time_t milli)
Compare if the new time is earlier, and only remove-old/add-new if it
is. */
time_t diff = curlx_tvdiff(set, *nowp);
+
+ /* remove the previous timer first, if there */
+ multi_deltimeout(data, id);
+
if(diff > 0) {
/* the new expire time was later so just add it to the queue
and get out */
- multi_addtimeout(&data->state.timeoutlist, &set);
+ multi_addtimeout(data, &set, id);
return;
}
/* the new time is newer than the presently set one, so add the current
to the queue and update the head */
- multi_addtimeout(&data->state.timeoutlist, nowp);
+ multi_addtimeout(data, nowp, id);
/* Since this is an updated time, we must remove the previous entry from
the splay tree first and then re-add the new value */
@@ -2973,49 +2976,17 @@ void Curl_expire(struct Curl_easy *data, time_t milli)
}
/*
- * Curl_expire_latest()
+ * Curl_expire_done()
*
- * This is like Curl_expire() but will only add a timeout node to the list of
- * timers if there is no timeout that will expire before the given time.
- *
- * Use this function if the code logic risks calling this function many times
- * or if there's no particular conditional wait in the code for this specific
- * time-out period to expire.
+ * Removes the expire timer. Marks it as done.
*
*/
-void Curl_expire_latest(struct Curl_easy *data, time_t milli)
+void Curl_expire_done(struct Curl_easy *data, expire_id id)
{
- struct timeval *expire = &data->state.expiretime;
-
- struct timeval set;
-
- set = Curl_tvnow();
- set.tv_sec += (long)(milli / 1000);
- set.tv_usec += (long)(milli % 1000) * 1000;
-
- if(set.tv_usec >= 1000000) {
- set.tv_sec++;
- set.tv_usec -= 1000000;
- }
-
- if(expire->tv_sec || expire->tv_usec) {
- /* This means that the struct is added as a node in the splay tree.
- Compare if the new time is earlier, and only remove-old/add-new if it
- is. */
- time_t diff = curlx_tvdiff(set, *expire);
- if((diff > 0) && (diff < milli)) {
- /* if the new expire time is later than the top time, skip it, but not
- if the diff is larger than the new offset since then the previous
- time is already expired! */
- return;
- }
- }
-
- /* Just add the timeout like normal */
- Curl_expire(data, milli);
+ /* remove the timer, if there */
+ multi_deltimeout(data, id);
}
-
/*
* Curl_expire_clear()
*
@@ -3044,8 +3015,9 @@ void Curl_expire_clear(struct Curl_easy *data)
infof(data, "Internal error clearing splay node = %d\n", rc);
/* flush the timeout list too */
- while(list->size > 0)
+ while(list->size > 0) {
Curl_llist_remove(list, list->tail, NULL);
+ }
#ifdef DEBUGBUILD
infof(data, "Expire cleared\n");
@@ -3118,7 +3090,7 @@ void Curl_multi_process_pending_handles(struct Curl_multi *multi)
Curl_llist_remove(&multi->pending, e, NULL);
/* Make sure that the handle will be processed soonish. */
- Curl_expire_latest(data, 0);
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
}
e = next; /* operate on next handle */
diff --git a/Utilities/cmcurl/lib/multihandle.h b/Utilities/cmcurl/lib/multihandle.h
index 915b857fe5..e6ffbf5b68 100644
--- a/Utilities/cmcurl/lib/multihandle.h
+++ b/Utilities/cmcurl/lib/multihandle.h
@@ -25,6 +25,7 @@
#include "conncache.h"
struct Curl_message {
+ struct curl_llist_element list;
/* the 'CURLMsg' is the part that is visible to the external user */
struct CURLMsg extmsg;
};
diff --git a/Utilities/cmcurl/lib/multiif.h b/Utilities/cmcurl/lib/multiif.h
index e5de1fc493..a877571a00 100644
--- a/Utilities/cmcurl/lib/multiif.h
+++ b/Utilities/cmcurl/lib/multiif.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
@@ -25,9 +25,10 @@
/*
* Prototypes for library-wide functions provided by multi.c
*/
-void Curl_expire(struct Curl_easy *data, time_t milli);
+
+void Curl_expire(struct Curl_easy *data, time_t milli, expire_id);
void Curl_expire_clear(struct Curl_easy *data);
-void Curl_expire_latest(struct Curl_easy *data, time_t milli);
+void Curl_expire_done(struct Curl_easy *data, expire_id id);
bool Curl_pipeline_wanted(const struct Curl_multi* multi, int bits);
void Curl_multi_handlePipeBreak(struct Curl_easy *data);
diff --git a/Utilities/cmcurl/lib/pingpong.c b/Utilities/cmcurl/lib/pingpong.c
index b833fcd4c1..5ed79b7189 100644
--- a/Utilities/cmcurl/lib/pingpong.c
+++ b/Utilities/cmcurl/lib/pingpong.c
@@ -286,7 +286,8 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
/* number of bytes in the current line, so far */
perline = (ssize_t)(ptr-pp->linestart_resp);
- while((pp->nread_resp<BUFSIZE) && (keepon && !result)) {
+ while((pp->nread_resp < (size_t)data->set.buffer_size) &&
+ (keepon && !result)) {
if(pp->cache) {
/* we had data in the "cache", copy that instead of doing an actual
@@ -296,7 +297,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
* it would have been populated with something of size int to begin
* with, even though its datatype may be larger than an int.
*/
- DEBUGASSERT((ptr+pp->cache_size) <= (buf+BUFSIZE+1));
+ DEBUGASSERT((ptr+pp->cache_size) <= (buf+data->set.buffer_size+1));
memcpy(ptr, pp->cache, pp->cache_size);
gotbytes = (ssize_t)pp->cache_size;
free(pp->cache); /* free the cache */
@@ -308,8 +309,10 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
enum protection_level prot = conn->data_prot;
conn->data_prot = PROT_CLEAR;
#endif
- DEBUGASSERT((ptr+BUFSIZE-pp->nread_resp) <= (buf+BUFSIZE+1));
- result = Curl_read(conn, sockfd, ptr, BUFSIZE-pp->nread_resp,
+ DEBUGASSERT((ptr + data->set.buffer_size - pp->nread_resp) <=
+ (buf + data->set.buffer_size + 1));
+ result = Curl_read(conn, sockfd, ptr,
+ data->set.buffer_size - pp->nread_resp,
&gotbytes);
#ifdef HAVE_GSSAPI
DEBUGASSERT(prot > PROT_NONE && prot < PROT_LAST);
@@ -402,7 +405,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
}
else if(keepon) {
- if((perline == gotbytes) && (gotbytes > BUFSIZE/2)) {
+ if((perline == gotbytes) && (gotbytes > data->set.buffer_size/2)) {
/* We got an excessive line without newlines and we need to deal
with it. We keep the first bytes of the line then we throw
away the rest. */
@@ -414,7 +417,7 @@ CURLcode Curl_pp_readresp(curl_socket_t sockfd,
interested in the first piece */
clipamount = 40;
}
- else if(pp->nread_resp > BUFSIZE/2) {
+ else if(pp->nread_resp > (size_t)data->set.buffer_size/2) {
/* We got a large chunk of data and there's potentially still
trailing data to take care of, so we put any such part in the
"cache", clear the buffer to make space and restart. */
diff --git a/Utilities/cmcurl/lib/pipeline.c b/Utilities/cmcurl/lib/pipeline.c
index 4a14fddfe8..b8d2037452 100644
--- a/Utilities/cmcurl/lib/pipeline.c
+++ b/Utilities/cmcurl/lib/pipeline.c
@@ -38,16 +38,15 @@
#include "memdebug.h"
struct site_blacklist_entry {
- char *hostname;
+ struct curl_llist_element list;
unsigned short port;
+ char hostname[1];
};
static void site_blacklist_llist_dtor(void *user, void *element)
{
struct site_blacklist_entry *entry = element;
(void)user;
-
- Curl_safefree(entry->hostname);
free(entry);
}
@@ -94,8 +93,8 @@ bool Curl_pipeline_penalized(struct Curl_easy *data,
static CURLcode addHandleToPipeline(struct Curl_easy *data,
struct curl_llist *pipeline)
{
- if(!Curl_llist_insert_next(pipeline, pipeline->tail, data))
- return CURLE_OUT_OF_MEMORY;
+ Curl_llist_insert_next(pipeline, pipeline->tail, data,
+ &data->pipeline_queue);
return CURLE_OK;
}
@@ -114,7 +113,7 @@ CURLcode Curl_add_handle_to_pipeline(struct Curl_easy *handle,
if(pipeline == &conn->send_pipe && sendhead != conn->send_pipe.head) {
/* this is a new one as head, expire it */
Curl_pipeline_leave_write(conn); /* not in use yet */
- Curl_expire(conn->send_pipe.head->ptr, 0);
+ Curl_expire(conn->send_pipe.head->ptr, 0, EXPIRE_RUN_NOW);
}
#if 0 /* enable for pipeline debugging */
@@ -149,7 +148,7 @@ void Curl_move_handle_from_send_to_recv_pipe(struct Curl_easy *handle,
infof(conn->data, "%p is at send pipe head B!\n",
(void *)conn->send_pipe.head->ptr);
#endif
- Curl_expire(conn->send_pipe.head->ptr, 0);
+ Curl_expire(conn->send_pipe.head->ptr, 0, EXPIRE_RUN_NOW);
}
/* The receiver's list is not really interesting here since either this
@@ -202,24 +201,17 @@ CURLMcode Curl_pipeline_set_site_blacklist(char **sites,
/* Parse the URLs and populate the list */
while(*sites) {
- char *hostname;
char *port;
struct site_blacklist_entry *entry;
- hostname = strdup(*sites);
- if(!hostname) {
- Curl_llist_destroy(list, NULL);
- return CURLM_OUT_OF_MEMORY;
- }
-
- entry = malloc(sizeof(struct site_blacklist_entry));
+ entry = malloc(sizeof(struct site_blacklist_entry) + strlen(*sites));
if(!entry) {
- free(hostname);
Curl_llist_destroy(list, NULL);
return CURLM_OUT_OF_MEMORY;
}
+ strcpy(entry->hostname, *sites);
- port = strchr(hostname, ':');
+ port = strchr(entry->hostname, ':');
if(port) {
*port = '\0';
port++;
@@ -230,14 +222,7 @@ CURLMcode Curl_pipeline_set_site_blacklist(char **sites,
entry->port = 80;
}
- entry->hostname = hostname;
-
- if(!Curl_llist_insert_next(list, list->tail, entry)) {
- site_blacklist_llist_dtor(NULL, entry);
- Curl_llist_destroy(list, NULL);
- return CURLM_OUT_OF_MEMORY;
- }
-
+ Curl_llist_insert_next(list, list->tail, entry, &entry->list);
sites++;
}
}
@@ -274,6 +259,11 @@ bool Curl_pipeline_server_blacklisted(struct Curl_easy *handle,
return FALSE;
}
+struct blacklist_node {
+ struct curl_llist_element list;
+ char server_name[1];
+};
+
CURLMcode Curl_pipeline_set_server_blacklist(char **servers,
struct curl_llist *list)
{
@@ -286,20 +276,18 @@ CURLMcode Curl_pipeline_set_server_blacklist(char **servers,
/* Parse the URLs and populate the list */
while(*servers) {
- char *server_name;
-
- server_name = strdup(*servers);
- if(!server_name) {
- Curl_llist_destroy(list, NULL);
- return CURLM_OUT_OF_MEMORY;
- }
+ struct blacklist_node *n;
+ size_t len = strlen(*servers);
- if(!Curl_llist_insert_next(list, list->tail, server_name)) {
+ n = malloc(sizeof(struct blacklist_node) + len);
+ if(!n) {
Curl_llist_destroy(list, NULL);
- Curl_safefree(server_name);
return CURLM_OUT_OF_MEMORY;
}
+ strcpy(n->server_name, *servers);
+ Curl_llist_insert_next(list, list->tail, n->server_name,
+ &n->list);
servers++;
}
}
diff --git a/Utilities/cmcurl/lib/rand.c b/Utilities/cmcurl/lib/rand.c
index 8a1408425a..b6f40ac0a7 100644
--- a/Utilities/cmcurl/lib/rand.c
+++ b/Utilities/cmcurl/lib/rand.c
@@ -47,10 +47,12 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
char *force_entropy = getenv("CURL_ENTROPY");
if(force_entropy) {
if(!seeded) {
+ unsigned int seed = 0;
size_t elen = strlen(force_entropy);
- size_t clen = sizeof(randseed);
+ size_t clen = sizeof(seed);
size_t min = elen < clen ? elen : clen;
- memcpy((char *)&randseed, force_entropy, min);
+ memcpy((char *)&seed, force_entropy, min);
+ randseed = ntohl(seed);
seeded = TRUE;
}
else
@@ -115,18 +117,63 @@ static CURLcode randit(struct Curl_easy *data, unsigned int *rnd)
*
*/
-CURLcode Curl_rand(struct Curl_easy *data, unsigned int *rndptr,
- unsigned int num)
+CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num)
{
CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
- unsigned int i;
- assert(num > 0);
+ DEBUGASSERT(num > 0);
- for(i = 0; i < num; i++) {
- result = randit(data, rndptr++);
+ while(num) {
+ unsigned int r;
+ size_t left = num < sizeof(unsigned int) ? num : sizeof(unsigned int);
+
+ result = randit(data, &r);
if(result)
return result;
+
+ while(left) {
+ *rnd++ = (unsigned char)(r & 0xFF);
+ r >>= 8;
+ --num;
+ --left;
+ }
}
+
+ return result;
+}
+
+/*
+ * Curl_rand_hex() fills the 'rnd' buffer with a given 'num' size with random
+ * hexadecimal digits PLUS a zero terminating byte. It must be an odd number
+ * size.
+ */
+
+CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
+ size_t num)
+{
+ CURLcode result = CURLE_BAD_FUNCTION_ARGUMENT;
+ const char *hex = "0123456789abcdef";
+ unsigned char buffer[128];
+ unsigned char *bufp = buffer;
+ DEBUGASSERT(num > 1);
+
+ if((num/2 >= sizeof(buffer)) || !(num&1))
+ /* make sure it fits in the local buffer and that it is an odd number! */
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+
+ num--; /* save one for zero termination */
+
+ result = Curl_rand(data, buffer, num/2);
+ if(result)
+ return result;
+
+ while(num) {
+ *rnd++ = hex[(*bufp & 0xF0)>>4];
+ *rnd++ = hex[*bufp & 0x0F];
+ bufp++;
+ num -= 2;
+ }
+ *rnd = 0;
+
return result;
}
diff --git a/Utilities/cmcurl/lib/rand.h b/Utilities/cmcurl/lib/rand.h
index 0f8986120e..c6fae35537 100644
--- a/Utilities/cmcurl/lib/rand.h
+++ b/Utilities/cmcurl/lib/rand.h
@@ -7,7 +7,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -23,7 +23,7 @@
***************************************************************************/
/*
- * Curl_rand() stores 'num' number of random unsigned integers in the buffer
+ * Curl_rand() stores 'num' number of random unsigned characters in the buffer
* 'rnd' points to.
*
* If libcurl is built without TLS support or with a TLS backend that lacks a
@@ -37,7 +37,11 @@
* easy handle!
*
*/
-CURLcode Curl_rand(struct Curl_easy *data, unsigned int *rnd,
- unsigned int num);
+CURLcode Curl_rand(struct Curl_easy *data, unsigned char *rnd, size_t num);
+
+/* Same as above but outputs only random lowercase hex characters.
+ Does NOT terminate.*/
+CURLcode Curl_rand_hex(struct Curl_easy *data, unsigned char *rnd,
+ size_t num);
#endif /* HEADER_CURL_RAND_H */
diff --git a/Utilities/cmcurl/lib/sendf.c b/Utilities/cmcurl/lib/sendf.c
index 84b6b4b2fd..595c361776 100644
--- a/Utilities/cmcurl/lib/sendf.c
+++ b/Utilities/cmcurl/lib/sendf.c
@@ -149,7 +149,7 @@ static void pre_receive_plain(struct connectdata *conn, int num)
/* Have some incoming data */
if(!psnd->buffer) {
/* Use buffer double default size for intermediate buffer */
- psnd->allocated_size = 2 * BUFSIZE;
+ psnd->allocated_size = 2 * conn->data->set.buffer_size;
psnd->buffer = malloc(psnd->allocated_size);
psnd->recv_size = 0;
psnd->recv_processed = 0;
@@ -243,21 +243,20 @@ void Curl_failf(struct Curl_easy *data, const char *fmt, ...)
{
va_list ap;
size_t len;
+ char error[CURL_ERROR_SIZE + 2];
va_start(ap, fmt);
- vsnprintf(data->state.buffer, BUFSIZE, fmt, ap);
+ vsnprintf(error, CURL_ERROR_SIZE, fmt, ap);
+ len = strlen(error);
if(data->set.errorbuffer && !data->state.errorbuf) {
- snprintf(data->set.errorbuffer, CURL_ERROR_SIZE, "%s", data->state.buffer);
+ strcpy(data->set.errorbuffer, error);
data->state.errorbuf = TRUE; /* wrote error string */
}
if(data->set.verbose) {
- len = strlen(data->state.buffer);
- if(len < BUFSIZE - 1) {
- data->state.buffer[len] = '\n';
- data->state.buffer[++len] = '\0';
- }
- Curl_debug(data, CURLINFO_TEXT, data->state.buffer, len, NULL);
+ error[len] = '\n';
+ error[++len] = '\0';
+ Curl_debug(data, CURLINFO_TEXT, error, len, NULL);
}
va_end(ap);
@@ -694,9 +693,10 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
ssize_t nread = 0;
size_t bytesfromsocket = 0;
char *buffertofill = NULL;
+ struct Curl_easy *data = conn->data;
/* if HTTP/1 pipelining is both wanted and possible */
- bool pipelining = Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1) &&
+ bool pipelining = Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) &&
(conn->bundle->multiuse == BUNDLE_PIPELINING);
/* Set 'num' to 0 or 1, depending on which socket that has been sent here.
@@ -722,13 +722,11 @@ CURLcode Curl_read(struct connectdata *conn, /* connection data */
}
/* If we come here, it means that there is no data to read from the buffer,
* so we read from the socket */
- bytesfromsocket = CURLMIN(sizerequested, BUFSIZE * sizeof(char));
+ bytesfromsocket = CURLMIN(sizerequested, MASTERBUF_SIZE);
buffertofill = conn->master_buffer;
}
else {
- bytesfromsocket = CURLMIN((long)sizerequested,
- conn->data->set.buffer_size ?
- conn->data->set.buffer_size : BUFSIZE);
+ bytesfromsocket = CURLMIN(sizerequested, (size_t)data->set.buffer_size);
buffertofill = buf;
}
@@ -753,21 +751,19 @@ static int showit(struct Curl_easy *data, curl_infotype type,
{
static const char s_infotype[CURLINFO_END][3] = {
"* ", "< ", "> ", "{ ", "} ", "{ ", "} " };
+ int rc = 0;
#ifdef CURL_DOES_CONVERSIONS
- char buf[BUFSIZE+1];
+ char *buf = NULL;
size_t conv_size = 0;
switch(type) {
case CURLINFO_HEADER_OUT:
- /* assume output headers are ASCII */
- /* copy the data into my buffer so the original is unchanged */
- if(size > BUFSIZE) {
- size = BUFSIZE; /* truncate if necessary */
- buf[BUFSIZE] = '\0';
- }
+ buf = Curl_memdup(ptr, size);
+ if(!buf)
+ return 1;
conv_size = size;
- memcpy(buf, ptr, size);
+
/* Special processing is needed for this block if it
* contains both headers and data (separated by CRLFCRLF).
* We want to convert just the headers, leaving the data as-is.
@@ -795,26 +791,29 @@ static int showit(struct Curl_easy *data, curl_infotype type,
#endif /* CURL_DOES_CONVERSIONS */
if(data->set.fdebug)
- return (*data->set.fdebug)(data, type, ptr, size,
- data->set.debugdata);
-
- switch(type) {
- case CURLINFO_TEXT:
- case CURLINFO_HEADER_OUT:
- case CURLINFO_HEADER_IN:
- fwrite(s_infotype[type], 2, 1, data->set.err);
- fwrite(ptr, size, 1, data->set.err);
+ rc = (*data->set.fdebug)(data, type, ptr, size, data->set.debugdata);
+ else {
+ switch(type) {
+ case CURLINFO_TEXT:
+ case CURLINFO_HEADER_OUT:
+ case CURLINFO_HEADER_IN:
+ fwrite(s_infotype[type], 2, 1, data->set.err);
+ fwrite(ptr, size, 1, data->set.err);
#ifdef CURL_DOES_CONVERSIONS
- if(size != conv_size) {
- /* we had untranslated data so we need an explicit newline */
- fwrite("\n", 1, 1, data->set.err);
- }
+ if(size != conv_size) {
+ /* we had untranslated data so we need an explicit newline */
+ fwrite("\n", 1, 1, data->set.err);
+ }
#endif
- break;
- default: /* nada */
- break;
+ break;
+ default: /* nada */
+ break;
+ }
}
- return 0;
+#ifdef CURL_DOES_CONVERSIONS
+ free(buf);
+#endif
+ return rc;
}
int Curl_debug(struct Curl_easy *data, curl_infotype type,
diff --git a/Utilities/cmcurl/lib/smb.c b/Utilities/cmcurl/lib/smb.c
index 51b3434cbe..5b1ffa9b7c 100644
--- a/Utilities/cmcurl/lib/smb.c
+++ b/Utilities/cmcurl/lib/smb.c
@@ -607,7 +607,7 @@ static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg)
/* Check if there is data in the transfer buffer */
if(!smbc->send_size && smbc->upload_size) {
- int nread = smbc->upload_size > BUFSIZE ? BUFSIZE :
+ int nread = smbc->upload_size > UPLOAD_BUFSIZE ? UPLOAD_BUFSIZE :
(int) smbc->upload_size;
conn->data->req.upload_fromhere = conn->data->state.uploadbuffer;
result = Curl_fillreadbuffer(conn, nread, &nread);
diff --git a/Utilities/cmcurl/lib/smtp.c b/Utilities/cmcurl/lib/smtp.c
index adc346a693..fe064cb2f1 100644
--- a/Utilities/cmcurl/lib/smtp.c
+++ b/Utilities/cmcurl/lib/smtp.c
@@ -1591,7 +1591,7 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread)
if(!scratch || data->set.crlf) {
oldscratch = scratch;
- scratch = newscratch = malloc(2 * BUFSIZE);
+ scratch = newscratch = malloc(2 * data->set.buffer_size);
if(!newscratch) {
failf(data, "Failed to alloc scratch buffer!");
diff --git a/Utilities/cmcurl/lib/speedcheck.c b/Utilities/cmcurl/lib/speedcheck.c
index f0daf82c0b..8addedde59 100644
--- a/Utilities/cmcurl/lib/speedcheck.c
+++ b/Utilities/cmcurl/lib/speedcheck.c
@@ -67,7 +67,7 @@ CURLcode Curl_speedcheck(struct Curl_easy *data,
if(data->set.low_speed_limit)
/* if low speed limit is enabled, set the expire timer to make this
connection's speed get checked again in a second */
- Curl_expire_latest(data, 1000);
+ Curl_expire(data, 1000, EXPIRE_SPEEDCHECK);
return CURLE_OK;
}
diff --git a/Utilities/cmcurl/lib/ssh.c b/Utilities/cmcurl/lib/ssh.c
index 72fa06af73..00aeca9781 100644
--- a/Utilities/cmcurl/lib/ssh.c
+++ b/Utilities/cmcurl/lib/ssh.c
@@ -5,7 +5,7 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2017, 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
@@ -113,6 +113,7 @@
libssh2_sftp_symlink_ex((s), (p), curlx_uztoui(strlen(p)), \
(t), (m), LIBSSH2_SFTP_REALPATH)
+
/* Local functions: */
static const char *sftp_libssh2_strerror(int err);
static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc);
@@ -1837,8 +1838,9 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* seekerr == CURL_SEEKFUNC_CANTSEEK (can't seek to offset) */
do {
size_t readthisamountnow =
- (data->state.resume_from - passed > CURL_OFF_T_C(BUFSIZE)) ?
- BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
+ (data->state.resume_from - passed > data->set.buffer_size) ?
+ (size_t)data->set.buffer_size :
+ curlx_sotouz(data->state.resume_from - passed);
size_t actuallyread =
data->state.fread_func(data->state.buffer, 1,
@@ -1890,7 +1892,7 @@ static CURLcode ssh_statemach_act(struct connectdata *conn, bool *block)
/* since we don't really wait for anything at this point, we want the
state machine to move on as soon as possible so we set a very short
timeout here */
- Curl_expire(data, 0);
+ Curl_expire(data, 0, EXPIRE_RUN_NOW);
state(conn, SSH_STOP);
}
@@ -2814,7 +2816,7 @@ static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done)
}
static CURLcode ssh_block_statemach(struct connectdata *conn,
- bool duringconnect)
+ bool disconnect)
{
struct ssh_conn *sshc = &conn->proto.sshc;
CURLcode result = CURLE_OK;
@@ -2822,24 +2824,26 @@ static CURLcode ssh_block_statemach(struct connectdata *conn,
while((sshc->state != SSH_STOP) && !result) {
bool block;
- time_t left;
+ time_t left = 1000;
struct timeval now = Curl_tvnow();
result = ssh_statemach_act(conn, &block);
if(result)
break;
- if(Curl_pgrsUpdate(conn))
- return CURLE_ABORTED_BY_CALLBACK;
+ if(!disconnect) {
+ if(Curl_pgrsUpdate(conn))
+ return CURLE_ABORTED_BY_CALLBACK;
- result = Curl_speedcheck(data, now);
- if(result)
- break;
+ result = Curl_speedcheck(data, now);
+ if(result)
+ break;
- left = Curl_timeleft(data, NULL, duringconnect);
- if(left < 0) {
- failf(data, "Operation timed out");
- return CURLE_OPERATION_TIMEDOUT;
+ left = Curl_timeleft(data, NULL, FALSE);
+ if(left < 0) {
+ failf(data, "Operation timed out");
+ return CURLE_OPERATION_TIMEDOUT;
+ }
}
#ifdef HAVE_LIBSSH2_SESSION_BLOCK_DIRECTION
@@ -3055,7 +3059,7 @@ static CURLcode scp_disconnect(struct connectdata *conn, bool dead_connection)
state(conn, SSH_SESSION_DISCONNECT);
- result = ssh_block_statemach(conn, FALSE);
+ result = ssh_block_statemach(conn, TRUE);
}
return result;
@@ -3209,7 +3213,7 @@ static CURLcode sftp_disconnect(struct connectdata *conn, bool dead_connection)
if(conn->proto.sshc.ssh_session) {
/* only if there's a session still around to use! */
state(conn, SSH_SFTP_SHUTDOWN);
- result = ssh_block_statemach(conn, FALSE);
+ result = ssh_block_statemach(conn, TRUE);
}
DEBUGF(infof(conn->data, "SSH DISCONNECT is done\n"));
diff --git a/Utilities/cmcurl/lib/telnet.c b/Utilities/cmcurl/lib/telnet.c
index 5cceed2581..155d4b2608 100644
--- a/Utilities/cmcurl/lib/telnet.c
+++ b/Utilities/cmcurl/lib/telnet.c
@@ -81,10 +81,12 @@
} WHILE_FALSE
#define CURL_SB_GET(x) ((*x->subpointer++)&0xff)
-#define CURL_SB_PEEK(x) ((*x->subpointer)&0xff)
-#define CURL_SB_EOF(x) (x->subpointer >= x->subend)
#define CURL_SB_LEN(x) (x->subend - x->subpointer)
+/* For posterity:
+#define CURL_SB_PEEK(x) ((*x->subpointer)&0xff)
+#define CURL_SB_EOF(x) (x->subpointer >= x->subend) */
+
#ifdef CURL_DISABLE_VERBOSE_STRINGS
#define printoption(a,b,c,d) Curl_nop_stmt
#endif
@@ -1218,43 +1220,63 @@ CURLcode telrcv(struct connectdata *conn,
}
/* Escape and send a telnet data block */
-/* TODO: write large chunks of data instead of one byte at a time */
static CURLcode send_telnet_data(struct connectdata *conn,
char *buffer, ssize_t nread)
{
- unsigned char outbuf[2];
- ssize_t bytes_written, total_written;
- int out_count;
+ ssize_t escapes, i, j, outlen;
+ unsigned char *outbuf = NULL;
CURLcode result = CURLE_OK;
+ ssize_t bytes_written, total_written;
- while(!result && nread--) {
- outbuf[0] = *buffer++;
- out_count = 1;
- if(outbuf[0] == CURL_IAC)
- outbuf[out_count++] = CURL_IAC;
-
- total_written = 0;
- do {
- /* Make sure socket is writable to avoid EWOULDBLOCK condition */
- struct pollfd pfd[1];
- pfd[0].fd = conn->sock[FIRSTSOCKET];
- pfd[0].events = POLLOUT;
- switch(Curl_poll(pfd, 1, -1)) {
- case -1: /* error, abort writing */
- case 0: /* timeout (will never happen) */
- result = CURLE_SEND_ERROR;
- break;
- default: /* write! */
- bytes_written = 0;
- result = Curl_write(conn, conn->sock[FIRSTSOCKET],
- outbuf+total_written, out_count-total_written,
- &bytes_written);
- total_written += bytes_written;
- break;
- }
- /* handle partial write */
- } while(!result && total_written < out_count);
+ /* Determine size of new buffer after escaping */
+ escapes = 0;
+ for(i = 0; i < nread; i++)
+ if((unsigned char)buffer[i] == CURL_IAC)
+ escapes++;
+ outlen = nread + escapes;
+
+ if(outlen == nread)
+ outbuf = (unsigned char *)buffer;
+ else {
+ outbuf = malloc(nread + escapes + 1);
+ if(!outbuf)
+ return CURLE_OUT_OF_MEMORY;
+
+ j = 0;
+ for(i = 0; i < nread; i++) {
+ outbuf[j++] = buffer[i];
+ if((unsigned char)buffer[i] == CURL_IAC)
+ outbuf[j++] = CURL_IAC;
+ }
+ outbuf[j] = '\0';
}
+
+ total_written = 0;
+ while(!result && total_written < outlen) {
+ /* Make sure socket is writable to avoid EWOULDBLOCK condition */
+ struct pollfd pfd[1];
+ pfd[0].fd = conn->sock[FIRSTSOCKET];
+ pfd[0].events = POLLOUT;
+ switch(Curl_poll(pfd, 1, -1)) {
+ case -1: /* error, abort writing */
+ case 0: /* timeout (will never happen) */
+ result = CURLE_SEND_ERROR;
+ break;
+ default: /* write! */
+ bytes_written = 0;
+ result = Curl_write(conn, conn->sock[FIRSTSOCKET],
+ outbuf + total_written,
+ outlen - total_written,
+ &bytes_written);
+ total_written += bytes_written;
+ break;
+ }
+ }
+
+ /* Free malloc copy if escaped */
+ if(outbuf != (unsigned char *)buffer)
+ free(outbuf);
+
return result;
}
@@ -1414,7 +1436,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
/* Keep on listening and act on events */
while(keepon) {
- const DWORD buf_size = (DWORD)CURL_BUFSIZE(data->set.buffer_size);
+ const DWORD buf_size = (DWORD)data->set.buffer_size;
waitret = WaitForMultipleObjects(obj_count, objs, FALSE, wait_timeout);
switch(waitret) {
case WAIT_TIMEOUT:
@@ -1423,7 +1445,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
if(data->set.is_fread_set) {
size_t n;
/* read from user-supplied method */
- n = data->state.fread_func(buf, 1, BUFSIZE - 1, data->state.in);
+ n = data->state.fread_func(buf, 1, buf_size, data->state.in);
if(n == CURL_READFUNC_ABORT) {
keepon = FALSE;
result = CURLE_READ_ERROR;
@@ -1498,7 +1520,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
}
if(events.lNetworkEvents & FD_READ) {
/* read data from network */
- result = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
+ result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &nread);
/* read would've blocked. Loop again */
if(result == CURLE_AGAIN)
break;
@@ -1587,7 +1609,7 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
default: /* read! */
if(pfd[0].revents & POLLIN) {
/* read data from network */
- result = Curl_read(conn, sockfd, buf, BUFSIZE - 1, &nread);
+ result = Curl_read(conn, sockfd, buf, data->set.buffer_size, &nread);
/* read would've blocked. Loop again */
if(result == CURLE_AGAIN)
break;
@@ -1623,12 +1645,12 @@ static CURLcode telnet_do(struct connectdata *conn, bool *done)
nread = 0;
if(poll_cnt == 2) {
if(pfd[1].revents & POLLIN) { /* read from in file */
- nread = read(pfd[1].fd, buf, BUFSIZE - 1);
+ nread = read(pfd[1].fd, buf, data->set.buffer_size);
}
}
else {
/* read from user-supplied method */
- nread = (int)data->state.fread_func(buf, 1, BUFSIZE - 1,
+ nread = (int)data->state.fread_func(buf, 1, data->set.buffer_size,
data->state.in);
if(nread == CURL_READFUNC_ABORT) {
keepon = FALSE;
diff --git a/Utilities/cmcurl/lib/tftp.c b/Utilities/cmcurl/lib/tftp.c
index 098b1bb9a1..b2b3efe0c5 100644
--- a/Utilities/cmcurl/lib/tftp.c
+++ b/Utilities/cmcurl/lib/tftp.c
@@ -1119,7 +1119,8 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
}
else {
/* The event is given by the TFTP packet time */
- state->event = (tftp_event_t)getrpacketevent(&state->rpacket);
+ unsigned short event = getrpacketevent(&state->rpacket);
+ state->event = (tftp_event_t)event;
switch(state->event) {
case TFTP_EVENT_DATA:
@@ -1138,9 +1139,12 @@ static CURLcode tftp_receive_packet(struct connectdata *conn)
}
break;
case TFTP_EVENT_ERROR:
- state->error = (tftp_error_t)getrpacketblock(&state->rpacket);
+ {
+ unsigned short error = getrpacketblock(&state->rpacket);
+ state->error = (tftp_error_t)error;
infof(data, "%s\n", (const char *)state->rpacket.data+4);
break;
+ }
case TFTP_EVENT_ACK:
break;
case TFTP_EVENT_OACK:
diff --git a/Utilities/cmcurl/lib/timeval.c b/Utilities/cmcurl/lib/timeval.c
index 0d6036b815..bed44c573f 100644
--- a/Utilities/cmcurl/lib/timeval.c
+++ b/Utilities/cmcurl/lib/timeval.c
@@ -141,9 +141,3 @@ double curlx_tvdiff_secs(struct timeval newer, struct timeval older)
(double)(newer.tv_usec-older.tv_usec)/1000000.0;
return (double)(newer.tv_usec-older.tv_usec)/1000000.0;
}
-
-/* return the number of seconds in the given input timeval struct */
-time_t Curl_tvlong(struct timeval t1)
-{
- return t1.tv_sec;
-}
diff --git a/Utilities/cmcurl/lib/timeval.h b/Utilities/cmcurl/lib/timeval.h
index 09f8b3a20e..33969354d5 100644
--- a/Utilities/cmcurl/lib/timeval.h
+++ b/Utilities/cmcurl/lib/timeval.h
@@ -46,8 +46,6 @@ time_t curlx_tvdiff(struct timeval t1, struct timeval t2);
*/
double curlx_tvdiff_secs(struct timeval t1, struct timeval t2);
-time_t Curl_tvlong(struct timeval t1);
-
/* These two defines below exist to provide the older API for library
internals only. */
#define Curl_tvnow() curlx_tvnow()
diff --git a/Utilities/cmcurl/lib/transfer.c b/Utilities/cmcurl/lib/transfer.c
index 1f6d26d7f5..43e8f64aa8 100644
--- a/Utilities/cmcurl/lib/transfer.c
+++ b/Utilities/cmcurl/lib/transfer.c
@@ -405,8 +405,7 @@ static CURLcode readwrite_data(struct Curl_easy *data,
/* This is where we loop until we have read everything there is to
read or we get a CURLE_AGAIN */
do {
- size_t buffersize = data->set.buffer_size?
- data->set.buffer_size : BUFSIZE;
+ size_t buffersize = data->set.buffer_size;
size_t bytestoread = buffersize;
if(
@@ -681,8 +680,6 @@ static CURLcode readwrite_data(struct Curl_easy *data,
excess = (size_t)(k->bytecount + nread - k->maxdownload);
if(excess > 0 && !k->ignorebody) {
if(Curl_pipeline_wanted(conn->data->multi, CURLPIPE_HTTP1)) {
- /* The 'excess' amount below can't be more than BUFSIZE which
- always will fit in a size_t */
infof(data,
"Rewinding stream by : %zu"
" bytes on url %s (size = %" CURL_FORMAT_CURL_OFF_T
@@ -853,7 +850,6 @@ static CURLcode done_sending(struct connectdata *conn,
*/
static CURLcode readwrite_upload(struct Curl_easy *data,
struct connectdata *conn,
- struct SingleRequest *k,
int *didwhat)
{
ssize_t i, si;
@@ -861,6 +857,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
CURLcode result;
ssize_t nread; /* number of bytes read */
bool sending_http_headers = FALSE;
+ struct SingleRequest *k = &data->req;
if((k->bytecount == 0) && (k->writebytecount == 0))
Curl_pgrsTime(data, TIMER_STARTTRANSFER);
@@ -871,15 +868,15 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
/* only read more data if there's no upload data already
present in the upload buffer */
- if(0 == data->req.upload_present) {
+ if(0 == k->upload_present) {
/* init the "upload from here" pointer */
- data->req.upload_fromhere = k->uploadbuf;
+ k->upload_fromhere = data->state.uploadbuffer;
if(!k->upload_done) {
/* HTTP pollution, this should be written nicer to become more
protocol agnostic. */
int fillcount;
- struct HTTP *http = data->req.protop;
+ struct HTTP *http = k->protop;
if((k->exp100 == EXP100_SENDING_REQUEST) &&
(http->sending == HTTPSEND_BODY)) {
@@ -892,7 +889,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
*didwhat &= ~KEEP_SEND; /* we didn't write anything actually */
/* set a timeout for the multi interface */
- Curl_expire(data, data->set.expect_100_timeout);
+ Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT);
break;
}
@@ -905,7 +902,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
sending_http_headers = FALSE;
}
- result = Curl_fillreadbuffer(conn, BUFSIZE, &fillcount);
+ result = Curl_fillreadbuffer(conn, UPLOAD_BUFSIZE, &fillcount);
if(result)
return result;
@@ -926,7 +923,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
}
/* store number of bytes available for upload */
- data->req.upload_present = nread;
+ k->upload_present = nread;
/* convert LF to CRLF if so asked */
if((!sending_http_headers) && (
@@ -937,7 +934,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
(data->set.crlf))) {
/* Do we need to allocate a scratch buffer? */
if(!data->state.scratch) {
- data->state.scratch = malloc(2 * BUFSIZE);
+ data->state.scratch = malloc(2 * data->set.buffer_size);
if(!data->state.scratch) {
failf(data, "Failed to alloc scratch buffer!");
@@ -952,7 +949,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
* must be used instead of the escape sequences \r & \n.
*/
for(i = 0, si = 0; i < nread; i++, si++) {
- if(data->req.upload_fromhere[i] == 0x0a) {
+ if(k->upload_fromhere[i] == 0x0a) {
data->state.scratch[si++] = 0x0d;
data->state.scratch[si] = 0x0a;
if(!data->set.crlf) {
@@ -963,7 +960,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
}
}
else
- data->state.scratch[si] = data->req.upload_fromhere[i];
+ data->state.scratch[si] = k->upload_fromhere[i];
}
if(si != nread) {
@@ -972,10 +969,10 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
nread = si;
/* upload from the new (replaced) buffer instead */
- data->req.upload_fromhere = data->state.scratch;
+ k->upload_fromhere = data->state.scratch;
/* set the new amount too */
- data->req.upload_present = nread;
+ k->upload_present = nread;
}
}
@@ -986,7 +983,7 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
return result;
}
#endif /* CURL_DISABLE_SMTP */
- } /* if 0 == data->req.upload_present */
+ } /* if 0 == k->upload_present */
else {
/* We have a partial buffer left from a previous "round". Use
that instead of reading more data */
@@ -994,17 +991,17 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
/* write to socket (send away data) */
result = Curl_write(conn,
- conn->writesockfd, /* socket to send to */
- data->req.upload_fromhere, /* buffer pointer */
- data->req.upload_present, /* buffer size */
- &bytes_written); /* actually sent */
+ conn->writesockfd, /* socket to send to */
+ k->upload_fromhere, /* buffer pointer */
+ k->upload_present, /* buffer size */
+ &bytes_written); /* actually sent */
if(result)
return result;
if(data->set.verbose)
/* show the data before we change the pointer upload_fromhere */
- Curl_debug(data, CURLINFO_DATA_OUT, data->req.upload_fromhere,
+ Curl_debug(data, CURLINFO_DATA_OUT, k->upload_fromhere,
(size_t)bytes_written, conn);
k->writebytecount += bytes_written;
@@ -1015,20 +1012,20 @@ static CURLcode readwrite_upload(struct Curl_easy *data,
infof(data, "We are completely uploaded and fine\n");
}
- if(data->req.upload_present != bytes_written) {
+ if(k->upload_present != bytes_written) {
/* we only wrote a part of the buffer (if anything), deal with it! */
/* store the amount of bytes left in the buffer to write */
- data->req.upload_present -= bytes_written;
+ k->upload_present -= bytes_written;
/* advance the pointer where to find the buffer when the next send
is to happen */
- data->req.upload_fromhere += bytes_written;
+ k->upload_fromhere += bytes_written;
}
else {
/* we've uploaded that buffer now */
- data->req.upload_fromhere = k->uploadbuf;
- data->req.upload_present = 0; /* no more bytes left */
+ k->upload_fromhere = data->state.uploadbuffer;
+ k->upload_present = 0; /* no more bytes left */
if(k->upload_done) {
result = done_sending(conn, k);
@@ -1108,7 +1105,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
if((k->keepon & KEEP_SEND) && (select_res & CURL_CSELECT_OUT)) {
/* write */
- result = readwrite_upload(data, conn, k, &didwhat);
+ result = readwrite_upload(data, conn, &didwhat);
if(result)
return result;
}
@@ -1142,6 +1139,7 @@ CURLcode Curl_readwrite(struct connectdata *conn,
/* we've waited long enough, continue anyway */
k->exp100 = EXP100_SEND_DATA;
k->keepon |= KEEP_SEND;
+ Curl_expire_done(data, EXPIRE_100_TIMEOUT);
infof(data, "Done waiting for 100-continue\n");
}
}
@@ -1186,15 +1184,13 @@ CURLcode Curl_readwrite(struct connectdata *conn,
*/
(k->bytecount != (k->size + data->state.crlf_conversions)) &&
#endif /* CURL_DO_LINEEND_CONV */
- !data->req.newurl) {
+ !k->newurl) {
failf(data, "transfer closed with %" CURL_FORMAT_CURL_OFF_T
- " bytes remaining to read",
- k->size - k->bytecount);
+ " bytes remaining to read", k->size - k->bytecount);
return CURLE_PARTIAL_FILE;
}
- if(!(data->set.opt_no_body) &&
- k->chunk &&
- (conn->chunk.state != CHUNK_STOP)) {
+ if(!(data->set.opt_no_body) && k->chunk &&
+ (conn->chunk.state != CHUNK_STOP)) {
/*
* In chunked mode, return an error if the connection is closed prior to
* the empty (terminating) chunk is read.
@@ -1313,8 +1309,11 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
if(data->set.httpreq == HTTPREQ_PUT)
data->state.infilesize = data->set.filesize;
- else
+ else {
data->state.infilesize = data->set.postfieldsize;
+ if(data->set.postfields && (data->state.infilesize == -1))
+ data->state.infilesize = (curl_off_t)strlen(data->set.postfields);
+ }
/* If there is a list of cookie files to read, do it now! */
if(data->change.cookielist)
@@ -1343,10 +1342,10 @@ CURLcode Curl_pretransfer(struct Curl_easy *data)
Curl_pgrsStartNow(data);
if(data->set.timeout)
- Curl_expire(data, data->set.timeout);
+ Curl_expire(data, data->set.timeout, EXPIRE_TIMEOUT);
if(data->set.connecttimeout)
- Curl_expire(data, data->set.connecttimeout);
+ Curl_expire(data, data->set.connecttimeout, EXPIRE_CONNECTTIMEOUT);
/* In case the handle is re-used and an authentication method was picked
in the session we need to make sure we only use the one(s) we now
@@ -1628,9 +1627,7 @@ static char *concat_url(const char *base, const char *relurl)
* as given by the remote server and set up the new URL to request.
*/
CURLcode Curl_follow(struct Curl_easy *data,
- char *newurl, /* this 'newurl' is the Location: string,
- and it must be malloc()ed before passed
- here */
+ char *newurl, /* the Location: string */
followtype type) /* see transfer.h */
{
#ifdef CURL_DISABLE_HTTP
@@ -1643,33 +1640,36 @@ CURLcode Curl_follow(struct Curl_easy *data,
/* Location: redirect */
bool disallowport = FALSE;
+ bool reachedmax = FALSE;
if(type == FOLLOW_REDIR) {
if((data->set.maxredirs != -1) &&
- (data->set.followlocation >= data->set.maxredirs)) {
- failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs);
- return CURLE_TOO_MANY_REDIRECTS;
+ (data->set.followlocation >= data->set.maxredirs)) {
+ reachedmax = TRUE;
+ type = FOLLOW_FAKE; /* switch to fake to store the would-be-redirected
+ to URL */
}
+ else {
+ /* mark the next request as a followed location: */
+ data->state.this_is_a_follow = TRUE;
- /* mark the next request as a followed location: */
- data->state.this_is_a_follow = TRUE;
+ data->set.followlocation++; /* count location-followers */
- data->set.followlocation++; /* count location-followers */
+ if(data->set.http_auto_referer) {
+ /* We are asked to automatically set the previous URL as the referer
+ when we get the next URL. We pick the ->url field, which may or may
+ not be 100% correct */
- if(data->set.http_auto_referer) {
- /* We are asked to automatically set the previous URL as the referer
- when we get the next URL. We pick the ->url field, which may or may
- not be 100% correct */
+ if(data->change.referer_alloc) {
+ Curl_safefree(data->change.referer);
+ data->change.referer_alloc = FALSE;
+ }
- if(data->change.referer_alloc) {
- Curl_safefree(data->change.referer);
- data->change.referer_alloc = FALSE;
+ data->change.referer = strdup(data->change.url);
+ if(!data->change.referer)
+ return CURLE_OUT_OF_MEMORY;
+ data->change.referer_alloc = TRUE; /* yes, free this later */
}
-
- data->change.referer = strdup(data->change.url);
- if(!data->change.referer)
- return CURLE_OUT_OF_MEMORY;
- data->change.referer_alloc = TRUE; /* yes, free this later */
}
}
@@ -1681,7 +1681,6 @@ CURLcode Curl_follow(struct Curl_easy *data,
char *absolute = concat_url(data->change.url, newurl);
if(!absolute)
return CURLE_OUT_OF_MEMORY;
- free(newurl);
newurl = absolute;
}
else {
@@ -1697,8 +1696,6 @@ CURLcode Curl_follow(struct Curl_easy *data,
if(!newest)
return CURLE_OUT_OF_MEMORY;
strcpy_url(newest, newurl); /* create a space-free URL */
-
- free(newurl); /* that was no good */
newurl = newest; /* use this instead now */
}
@@ -1707,6 +1704,11 @@ CURLcode Curl_follow(struct Curl_easy *data,
/* we're only figuring out the new url if we would've followed locations
but now we're done so we can get out! */
data->info.wouldredirect = newurl;
+
+ if(reachedmax) {
+ failf(data, "Maximum (%ld) redirects followed", data->set.maxredirs);
+ return CURLE_TOO_MANY_REDIRECTS;
+ }
return CURLE_OK;
}
@@ -1720,7 +1722,6 @@ CURLcode Curl_follow(struct Curl_easy *data,
data->change.url = newurl;
data->change.url_alloc = TRUE;
- newurl = NULL; /* don't free! */
infof(data, "Issue another request to this URL: '%s'\n", data->change.url);
@@ -1947,7 +1948,7 @@ Curl_setup_transfer(
/* Set a timeout for the multi interface. Add the inaccuracy margin so
that we don't fire slightly too early and get denied to run. */
- Curl_expire(data, data->set.expect_100_timeout);
+ Curl_expire(data, data->set.expect_100_timeout, EXPIRE_100_TIMEOUT);
}
else {
if(data->state.expect100header)
diff --git a/Utilities/cmcurl/lib/url.c b/Utilities/cmcurl/lib/url.c
index caa28f5d44..87446dbca3 100644
--- a/Utilities/cmcurl/lib/url.c
+++ b/Utilities/cmcurl/lib/url.c
@@ -140,6 +140,19 @@ static CURLcode parse_login_details(const char *login, const size_t len,
char **optionsptr);
static unsigned int get_protocol_family(unsigned int protocol);
+#define READBUFFER_SIZE CURL_MAX_WRITE_SIZE
+#define READBUFFER_MAX CURL_MAX_READ_SIZE
+#define READBUFFER_MIN 1024
+
+/* Some parts of the code (e.g. chunked encoding) assume this buffer has at
+ * more than just a few bytes to play with. Don't let it become too small or
+ * bad things will happen.
+ */
+#if READBUFFER_SIZE < READBUFFER_MIN
+# error READBUFFER_SIZE is too small
+#endif
+
+
/*
* Protocol table.
*/
@@ -607,6 +620,7 @@ CURLcode Curl_init_userdefined(struct UserDefined *set)
set->expect_100_timeout = 1000L; /* Wait for a second by default. */
set->sep_headers = TRUE; /* separated header lists by default */
+ set->buffer_size = READBUFFER_SIZE;
Curl_http2_init_userset(set);
return result;
@@ -644,7 +658,7 @@ CURLcode Curl_open(struct Curl_easy **curl)
/* We do some initial setup here, all those fields that can't be just 0 */
- data->state.buffer = malloc(BUFSIZE + 1);
+ data->state.buffer = malloc(READBUFFER_SIZE + 1);
if(!data->state.buffer) {
DEBUGF(fprintf(stderr, "Error: malloc of buffer failed\n"));
result = CURLE_OUT_OF_MEMORY;
@@ -1009,8 +1023,8 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
* CURL_REDIR_POST_ALL - POST is kept as POST after 301, 302 and 303
* other - POST is kept as POST after 301 and 302
*/
- int postRedir = curlx_sltosi(va_arg(param, long));
- data->set.keep_post = postRedir & CURL_REDIR_POST_ALL;
+ arg = va_arg(param, long);
+ data->set.keep_post = arg & CURL_REDIR_POST_ALL;
}
break;
@@ -2061,13 +2075,19 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
/*
* Set what local port to bind the socket to when performing an operation.
*/
- data->set.localport = curlx_sltous(va_arg(param, long));
+ arg = va_arg(param, long);
+ if((arg < 0) || (arg > 65535))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.localport = curlx_sltous(arg);
break;
case CURLOPT_LOCALPORTRANGE:
/*
* Set number of local ports to try, starting with CURLOPT_LOCALPORT.
*/
- data->set.localportrange = curlx_sltosi(va_arg(param, long));
+ arg = va_arg(param, long);
+ if((arg < 0) || (arg > 65535))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.localportrange = curlx_sltosi(arg);
break;
case CURLOPT_KRBLEVEL:
/*
@@ -2284,22 +2304,26 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
* The application kindly asks for a differently sized receive buffer.
* If it seems reasonable, we'll use it.
*/
- data->set.buffer_size = va_arg(param, long);
-
- if(data->set.buffer_size > MAX_BUFSIZE)
- data->set.buffer_size = MAX_BUFSIZE; /* huge internal default */
- else if(data->set.buffer_size < 1)
- data->set.buffer_size = BUFSIZE;
+ arg = va_arg(param, long);
- /* Resize only if larger than default buffer size. */
- if(data->set.buffer_size > BUFSIZE) {
- data->state.buffer = realloc(data->state.buffer,
- data->set.buffer_size + 1);
- if(!data->state.buffer) {
+ if(arg > READBUFFER_MAX)
+ arg = READBUFFER_MAX;
+ else if(arg < 1)
+ arg = READBUFFER_SIZE;
+ else if(arg < READBUFFER_MIN)
+ arg = READBUFFER_MIN;
+
+ /* Resize if new size */
+ if(arg != data->set.buffer_size) {
+ char *newbuff = realloc(data->state.buffer, arg + 1);
+ if(!newbuff) {
DEBUGF(fprintf(stderr, "Error: realloc of buffer failed\n"));
result = CURLE_OUT_OF_MEMORY;
}
+ else
+ data->state.buffer = newbuff;
}
+ data->set.buffer_size = arg;
break;
@@ -2592,7 +2616,10 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
* know that an unsigned int will always hold the value so we blindly
* typecast to this type
*/
- data->set.scope_id = curlx_sltoui(va_arg(param, long));
+ arg = va_arg(param, long);
+ if((arg < 0) || (arg > 0xf))
+ return CURLE_BAD_FUNCTION_ARGUMENT;
+ data->set.scope_id = curlx_sltoui(arg);
break;
case CURLOPT_PROTOCOLS:
@@ -2794,13 +2821,17 @@ CURLcode Curl_setopt(struct Curl_easy *data, CURLoption option,
data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP; /* default to SRP */
break;
case CURLOPT_TLSAUTH_TYPE:
- if(strncasecompare((char *)va_arg(param, char *), "SRP", strlen("SRP")))
+ argptr = va_arg(param, char *);
+ if(!argptr ||
+ strncasecompare(argptr, "SRP", strlen("SRP")))
data->set.ssl.authtype = CURL_TLSAUTH_SRP;
else
data->set.ssl.authtype = CURL_TLSAUTH_NONE;
break;
case CURLOPT_PROXY_TLSAUTH_TYPE:
- if(strncasecompare((char *)va_arg(param, char *), "SRP", strlen("SRP")))
+ argptr = va_arg(param, char *);
+ if(!argptr ||
+ strncasecompare(argptr, "SRP", strlen("SRP")))
data->set.proxy_ssl.authtype = CURL_TLSAUTH_SRP;
else
data->set.proxy_ssl.authtype = CURL_TLSAUTH_NONE;
@@ -2935,8 +2966,7 @@ static void conn_reset_all_postponed_data(struct connectdata *conn)
conn_reset_postponed_data(conn, 1);
}
#else /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
-/* Use "do-nothing" macros instead of functions when workaround not used */
-#define conn_reset_postponed_data(c,n) do {} WHILE_FALSE
+/* Use "do-nothing" macro instead of function when workaround not used */
#define conn_reset_all_postponed_data(c) do {} WHILE_FALSE
#endif /* ! USE_RECV_BEFORE_SEND_WORKAROUND */
@@ -2993,6 +3023,7 @@ static void conn_free(struct connectdata *conn)
Curl_safefree(conn->http_proxy.host.rawalloc); /* http proxy name buffer */
Curl_safefree(conn->socks_proxy.host.rawalloc); /* socks proxy name buffer */
Curl_safefree(conn->master_buffer);
+ Curl_safefree(conn->connect_buffer);
conn_reset_all_postponed_data(conn);
@@ -3100,12 +3131,16 @@ static bool SocketIsDead(curl_socket_t sock)
}
/*
- * IsPipeliningPossible() returns TRUE if the options set would allow
- * pipelining/multiplexing and the connection is using a HTTP protocol.
+ * IsPipeliningPossible()
+ *
+ * Return a bitmask with the available pipelining and multiplexing options for
+ * the given requested connection.
*/
-static bool IsPipeliningPossible(const struct Curl_easy *handle,
- const struct connectdata *conn)
+static int IsPipeliningPossible(const struct Curl_easy *handle,
+ const struct connectdata *conn)
{
+ int avail = 0;
+
/* If a HTTP protocol and pipelining is enabled */
if((conn->handler->protocol & PROTO_FAMILY_HTTP) &&
(!conn->bits.protoconnstart || !conn->bits.close)) {
@@ -3115,14 +3150,14 @@ static bool IsPipeliningPossible(const struct Curl_easy *handle,
(handle->set.httpreq == HTTPREQ_GET ||
handle->set.httpreq == HTTPREQ_HEAD))
/* didn't ask for HTTP/1.0 and a GET or HEAD */
- return TRUE;
+ avail |= CURLPIPE_HTTP1;
if(Curl_pipeline_wanted(handle->multi, CURLPIPE_MULTIPLEX) &&
(handle->set.httpversion >= CURL_HTTP_VERSION_2))
/* allows HTTP/2 */
- return TRUE;
+ avail |= CURLPIPE_MULTIPLEX;
}
- return FALSE;
+ return avail;
}
int Curl_removeHandleFromPipeline(struct Curl_easy *handle,
@@ -3409,7 +3444,7 @@ ConnectionExists(struct Curl_easy *data,
struct connectdata *check;
struct connectdata *chosen = 0;
bool foundPendingCandidate = FALSE;
- bool canPipeline = IsPipeliningPossible(data, needle);
+ int canpipe = IsPipeliningPossible(data, needle);
struct connectbundle *bundle;
#ifdef USE_NTLM
@@ -3425,10 +3460,10 @@ ConnectionExists(struct Curl_easy *data,
*force_reuse = FALSE;
*waitpipe = FALSE;
- /* We can't pipe if the site is blacklisted */
- if(canPipeline && Curl_pipeline_site_blacklisted(data, needle)) {
- canPipeline = FALSE;
- }
+ /* We can't pipeline if the site is blacklisted */
+ if((canpipe & CURLPIPE_HTTP1) &&
+ Curl_pipeline_site_blacklisted(data, needle))
+ canpipe &= ~ CURLPIPE_HTTP1;
/* Look up the bundle with all the connections to this
particular host */
@@ -3448,8 +3483,8 @@ ConnectionExists(struct Curl_easy *data,
(bundle->multiuse == BUNDLE_MULTIPLEX ?
"can multiplex" : "serially")));
- /* We can't pipe if we don't know anything about the server */
- if(canPipeline) {
+ /* We can't pipeline if we don't know anything about the server */
+ if(canpipe) {
if(bundle->multiuse <= BUNDLE_UNKNOWN) {
if((bundle->multiuse == BUNDLE_UNKNOWN) && data->set.pipewait) {
infof(data, "Server doesn't support multi-use yet, wait\n");
@@ -3458,18 +3493,18 @@ ConnectionExists(struct Curl_easy *data,
}
infof(data, "Server doesn't support multi-use (yet)\n");
- canPipeline = FALSE;
+ canpipe = 0;
}
if((bundle->multiuse == BUNDLE_PIPELINING) &&
!Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1)) {
/* not asked for, switch off */
infof(data, "Could pipeline, but not asked to!\n");
- canPipeline = FALSE;
+ canpipe = 0;
}
else if((bundle->multiuse == BUNDLE_MULTIPLEX) &&
!Curl_pipeline_wanted(data->multi, CURLPIPE_MULTIPLEX)) {
infof(data, "Could multiplex, but not asked to!\n");
- canPipeline = FALSE;
+ canpipe = 0;
}
}
@@ -3490,20 +3525,21 @@ ConnectionExists(struct Curl_easy *data,
pipeLen = check->send_pipe.size + check->recv_pipe.size;
- if(canPipeline) {
+ if(canpipe) {
if(check->bits.protoconnstart && check->bits.close)
continue;
if(!check->bits.multiplex) {
- /* If not multiplexing, make sure the pipe has only GET requests */
+ /* If not multiplexing, make sure the connection is fine for HTTP/1
+ pipelining */
struct Curl_easy* sh = gethandleathead(&check->send_pipe);
struct Curl_easy* rh = gethandleathead(&check->recv_pipe);
if(sh) {
- if(!IsPipeliningPossible(sh, check))
+ if(!(IsPipeliningPossible(sh, check) & CURLPIPE_HTTP1))
continue;
}
else if(rh) {
- if(!IsPipeliningPossible(rh, check))
+ if(!(IsPipeliningPossible(rh, check) & CURLPIPE_HTTP1))
continue;
}
}
@@ -3611,7 +3647,7 @@ ConnectionExists(struct Curl_easy *data,
}
}
- if(!canPipeline && check->inuse)
+ if(!canpipe && check->inuse)
/* this request can't be pipelined but the checked connection is
already in use so we skip it */
continue;
@@ -3742,7 +3778,7 @@ ConnectionExists(struct Curl_easy *data,
continue;
}
#endif
- if(canPipeline) {
+ if(canpipe) {
/* We can pipeline if we want to. Let's continue looking for
the optimal connection to use, i.e the shortest pipe that is not
blacklisted. */
@@ -4203,7 +4239,7 @@ static struct connectdata *allocate_conn(struct Curl_easy *data)
if(Curl_pipeline_wanted(data->multi, CURLPIPE_HTTP1) &&
!conn->master_buffer) {
/* Allocate master_buffer to be used for HTTP/1 pipelining */
- conn->master_buffer = calloc(BUFSIZE, sizeof(char));
+ conn->master_buffer = calloc(MASTERBUF_SIZE, sizeof(char));
if(!conn->master_buffer)
goto error;
}
@@ -4430,6 +4466,7 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
#endif
protop = "file"; /* protocol string */
+ *prot_missing = !url_has_scheme;
}
else {
/* clear path */
@@ -4593,14 +4630,30 @@ static CURLcode parseurlandfillconn(struct Curl_easy *data,
size_t plen = strlen(path); /* new path, should be 1 byte longer than
the original */
- size_t urllen = strlen(data->change.url); /* original URL length */
-
size_t prefixlen = strlen(conn->host.name);
- if(!*prot_missing)
- prefixlen += strlen(protop) + strlen("://");
+ if(!*prot_missing) {
+ size_t protolen = strlen(protop);
+
+ if(curl_strnequal(protop, data->change.url, protolen))
+ prefixlen += protolen;
+ else {
+ failf(data, "<url> malformed");
+ return CURLE_URL_MALFORMAT;
+ }
+
+ if(curl_strnequal("://", &data->change.url[protolen], 3))
+ prefixlen += 3;
+ /* only file: is allowed to omit one or both slashes */
+ else if(curl_strnequal("file:", data->change.url, 5))
+ prefixlen += 1 + (data->change.url[5] == '/');
+ else {
+ failf(data, "<url> malformed");
+ return CURLE_URL_MALFORMAT;
+ }
+ }
- reurl = malloc(urllen + 2); /* 2 for zerobyte + slash */
+ reurl = malloc(prefixlen + plen + 1);
if(!reurl)
return CURLE_OUT_OF_MEMORY;
@@ -6961,7 +7014,6 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
k->bytecount = 0;
k->buf = data->state.buffer;
- k->uploadbuf = data->state.uploadbuffer;
k->hbufp = data->state.headerbuff;
k->ignorebody=FALSE;
@@ -6985,7 +7037,7 @@ CURLcode Curl_init_do(struct Curl_easy *data, struct connectdata *conn)
* Returns the family as a single bit protocol identifier.
*/
-unsigned int get_protocol_family(unsigned int protocol)
+static unsigned int get_protocol_family(unsigned int protocol)
{
unsigned int family;
diff --git a/Utilities/cmcurl/lib/urldata.h b/Utilities/cmcurl/lib/urldata.h
index 3c94553a18..d4a4a98dcd 100644
--- a/Utilities/cmcurl/lib/urldata.h
+++ b/Utilities/cmcurl/lib/urldata.h
@@ -200,12 +200,12 @@
#include <libssh2_sftp.h>
#endif /* HAVE_LIBSSH2_H */
-/* Download buffer size, keep it fairly big for speed reasons */
-#undef BUFSIZE
-#define BUFSIZE CURL_MAX_WRITE_SIZE
-#undef MAX_BUFSIZE
-#define MAX_BUFSIZE CURL_MAX_READ_SIZE
-#define CURL_BUFSIZE(x) ((x)?(x):(BUFSIZE))
+/* The upload buffer size, should not be smaller than CURL_MAX_WRITE_SIZE, as
+ it needs to hold a full buffer as could be sent in a write callback */
+#define UPLOAD_BUFSIZE CURL_MAX_WRITE_SIZE
+
+/* The "master buffer" is for HTTP pipelining */
+#define MASTERBUF_SIZE 16384
/* Initial size of the buffer to store headers in, it'll be enlarged in case
of need. */
@@ -333,6 +333,11 @@ struct ssl_connect_data {
size_t encdata_length, decdata_length;
size_t encdata_offset, decdata_offset;
unsigned char *encdata_buffer, *decdata_buffer;
+ /* encdata_is_incomplete: if encdata contains only a partial record that
+ can't be decrypted without another Curl_read_plain (that is, status is
+ SEC_E_INCOMPLETE_MESSAGE) then set this true. after Curl_read_plain writes
+ more bytes into encdata then set this back to false. */
+ bool encdata_is_incomplete;
unsigned long req_flags, ret_flags;
CURLcode recv_unrecoverable_err; /* schannel_recv had an unrecoverable err */
bool recv_sspi_close_notify; /* true if connection closed by close_notify */
@@ -716,7 +721,6 @@ struct SingleRequest {
long bodywrites;
char *buf;
- char *uploadbuf;
curl_socket_t maxfd;
int keepon;
@@ -898,6 +902,8 @@ struct connectdata {
connection is used! */
struct Curl_easy *data;
+ struct curl_llist_element bundle_node; /* conncache */
+
/* chunk is for HTTP chunked encoding, but is in the general connectdata
struct only because we can do just about any protocol through a HTTP proxy
and a HTTP proxy may in fact respond using chunked encoding */
@@ -1138,6 +1144,7 @@ struct connectdata {
struct connectbundle *bundle; /* The bundle we are member of */
int negnpn; /* APLN or NPN TLS negotiated protocol, CURL_HTTP_VERSION* */
+ char *connect_buffer; /* for CONNECT business */
#ifdef USE_UNIX_SOCKETS
char *unix_domain_socket;
@@ -1307,6 +1314,30 @@ struct tempbuf {
Curl_client_write() */
};
+/* Timers */
+typedef enum {
+ EXPIRE_100_TIMEOUT,
+ EXPIRE_ASYNC_NAME,
+ EXPIRE_CONNECTTIMEOUT,
+ EXPIRE_DNS_PER_NAME,
+ EXPIRE_HAPPY_EYEBALLS,
+ EXPIRE_MULTI_PENDING,
+ EXPIRE_RUN_NOW,
+ EXPIRE_SPEEDCHECK,
+ EXPIRE_TIMEOUT,
+ EXPIRE_TOOFAST,
+ EXPIRE_LAST /* not an actual timer, used as a marker only */
+} expire_id;
+
+/*
+ * One instance for each timeout an easy handle can set.
+ */
+struct time_node {
+ struct curl_llist_element list;
+ struct timeval time;
+ expire_id eid;
+};
+
struct UrlState {
/* Points to the connection cache */
@@ -1326,7 +1357,7 @@ struct UrlState {
size_t headersize; /* size of the allocation */
char *buffer; /* download buffer */
- char uploadbuffer[BUFSIZE+1]; /* upload buffer */
+ char uploadbuffer[UPLOAD_BUFSIZE+1]; /* upload buffer */
curl_off_t current_speed; /* the ProgressShow() function sets this,
bytes / second */
bool this_is_a_follow; /* this is a followed Location: request */
@@ -1342,7 +1373,7 @@ struct UrlState {
long sessionage; /* number of the most recent session */
unsigned int tempcount; /* number of entries in use in tempwrite, 0 - 3 */
struct tempbuf tempwrite[3]; /* BOTH, HEADER, BODY */
- char *scratch; /* huge buffer[BUFSIZE*2] when doing upload CRLF replacing */
+ char *scratch; /* huge buffer[set.buffer_size*2] for upload CRLF replacing */
bool errorbuf; /* Set to TRUE if the error buffer is already filled in.
This must be set to FALSE every time _easy_perform() is
called. */
@@ -1375,6 +1406,7 @@ struct UrlState {
struct timeval expiretime; /* set this with Curl_expire() only */
struct Curl_tree timenode; /* for the splay stuff */
struct curl_llist timeoutlist; /* list of pending timeouts */
+ struct time_node expires[EXPIRE_LAST]; /* nodes for each expire type */
/* a place to store the most recently set FTP entrypath */
char *most_recent_ftp_entrypath;
@@ -1804,6 +1836,8 @@ struct Curl_easy {
struct Curl_easy *prev;
struct connectdata *easy_conn; /* the "unit's" connection */
+ struct curl_llist_element connect_queue;
+ struct curl_llist_element pipeline_queue;
CURLMstate mstate; /* the handle's state */
CURLcode result; /* previous result */
diff --git a/Utilities/cmcurl/lib/vauth/digest.c b/Utilities/cmcurl/lib/vauth/digest.c
index 31d25cfa10..185098ed68 100644
--- a/Utilities/cmcurl/lib/vauth/digest.c
+++ b/Utilities/cmcurl/lib/vauth/digest.c
@@ -205,7 +205,7 @@ static CURLcode auth_digest_get_qop_values(const char *options, int *value)
{
char *tmp;
char *token;
- char *tok_buf;
+ char *tok_buf = NULL;
/* Initialise the output */
*value = 0;
@@ -360,7 +360,6 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
char qop_options[64];
int qop_values;
char cnonce[33];
- unsigned int entropy[4];
char nonceCount[] = "00000001";
char method[] = "AUTHENTICATE";
char qop[] = DIGEST_QOP_VALUE_STRING_AUTH;
@@ -387,15 +386,11 @@ CURLcode Curl_auth_create_digest_md5_message(struct Curl_easy *data,
if(!(qop_values & DIGEST_QOP_VALUE_AUTH))
return CURLE_BAD_CONTENT_ENCODING;
- /* Generate 16 bytes of random data */
- result = Curl_rand(data, &entropy[0], 4);
+ /* Generate 32 random hex chars, 32 bytes + 1 zero termination */
+ result = Curl_rand_hex(data, (unsigned char *)cnonce, sizeof(cnonce));
if(result)
return result;
- /* Convert the random data into a 32 byte hex string */
- snprintf(cnonce, sizeof(cnonce), "%08x%08x%08x%08x",
- entropy[0], entropy[1], entropy[2], entropy[3]);
-
/* So far so good, now calculate A1 and H(A1) according to RFC 2831 */
ctxt = Curl_MD5_init(Curl_DIGEST_MD5);
if(!ctxt)
@@ -563,7 +558,7 @@ CURLcode Curl_auth_decode_digest_http_message(const char *chlg,
return CURLE_OUT_OF_MEMORY;
}
else if(strcasecompare(value, "qop")) {
- char *tok_buf;
+ char *tok_buf = NULL;
/* Tokenize the list and choose auth if possible, use a temporary
clone of the buffer since strtok_r() ruins it */
tmp = strdup(content);
@@ -684,12 +679,10 @@ CURLcode Curl_auth_create_digest_http_message(struct Curl_easy *data,
digest->nc = 1;
if(!digest->cnonce) {
- unsigned int rnd[4];
- result = Curl_rand(data, &rnd[0], 4);
+ result = Curl_rand_hex(data, (unsigned char *)cnoncebuf,
+ sizeof(cnoncebuf));
if(result)
return result;
- snprintf(cnoncebuf, sizeof(cnoncebuf), "%08x%08x%08x%08x",
- rnd[0], rnd[1], rnd[2], rnd[3]);
result = Curl_base64_encode(data, cnoncebuf, strlen(cnoncebuf),
&cnonce, &cnonce_sz);
diff --git a/Utilities/cmcurl/lib/vauth/ntlm.c b/Utilities/cmcurl/lib/vauth/ntlm.c
index d02eec491c..42196455f6 100644
--- a/Utilities/cmcurl/lib/vauth/ntlm.c
+++ b/Utilities/cmcurl/lib/vauth/ntlm.c
@@ -555,10 +555,10 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
#if defined(USE_NTRESPONSES) && defined(USE_NTLM_V2)
if(ntlm->target_info_len) {
unsigned char ntbuffer[0x18];
- unsigned int entropy[2];
+ unsigned char entropy[8];
unsigned char ntlmv2hash[0x18];
- result = Curl_rand(data, &entropy[0], 2);
+ result = Curl_rand(data, entropy, 8);
if(result)
return result;
@@ -572,15 +572,13 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
return result;
/* LMv2 response */
- result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash,
- (unsigned char *)&entropy[0],
+ result = Curl_ntlm_core_mk_lmv2_resp(ntlmv2hash, entropy,
&ntlm->nonce[0], lmresp);
if(result)
return result;
/* NTLMv2 response */
- result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash,
- (unsigned char *)&entropy[0],
+ result = Curl_ntlm_core_mk_ntlmv2_resp(ntlmv2hash, entropy,
ntlm, &ntlmv2resp, &ntresplen);
if(result)
return result;
@@ -596,10 +594,10 @@ CURLcode Curl_auth_create_ntlm_type3_message(struct Curl_easy *data,
unsigned char ntbuffer[0x18];
unsigned char tmp[0x18];
unsigned char md5sum[MD5_DIGEST_LENGTH];
- unsigned int entropy[2];
+ unsigned char entropy[8];
/* Need to create 8 bytes random data */
- result = Curl_rand(data, &entropy[0], 2);
+ result = Curl_rand(data, entropy, 8);
if(result)
return result;
diff --git a/Utilities/cmcurl/lib/vtls/cyassl.c b/Utilities/cmcurl/lib/vtls/cyassl.c
index 5f51ad5f99..01bfdabd1d 100644
--- a/Utilities/cmcurl/lib/vtls/cyassl.c
+++ b/Utilities/cmcurl/lib/vtls/cyassl.c
@@ -44,6 +44,38 @@ and that's a problem since options.h hasn't been included yet. */
#include <cyassl/options.h>
#endif
+/* To determine what functions are available we rely on one or both of:
+ - the user's options.h generated by CyaSSL/wolfSSL
+ - the symbols detected by curl's configure
+ Since they are markedly different from one another, and one or the other may
+ not be available, we do some checking below to bring things in sync. */
+
+/* HAVE_ALPN is wolfSSL's build time symbol for enabling ALPN in options.h. */
+#ifndef HAVE_ALPN
+#ifdef HAVE_WOLFSSL_USEALPN
+#define HAVE_ALPN
+#endif
+#endif
+
+/* WOLFSSL_ALLOW_SSLV3 is wolfSSL's build time symbol for enabling SSLv3 in
+ options.h, but is only seen in >= 3.6.6 since that's when they started
+ disabling SSLv3 by default. */
+#ifndef WOLFSSL_ALLOW_SSLV3
+#if (LIBCYASSL_VERSION_HEX < 0x03006006) || \
+ defined(HAVE_WOLFSSLV3_CLIENT_METHOD)
+#define WOLFSSL_ALLOW_SSLV3
+#endif
+#endif
+
+/* HAVE_SUPPORTED_CURVES is wolfSSL's build time symbol for enabling the ECC
+ supported curve extension in options.h. Note ECC is enabled separately. */
+#ifndef HAVE_SUPPORTED_CURVES
+#if defined(HAVE_CYASSL_CTX_USESUPPORTEDCURVE) || \
+ defined(HAVE_WOLFSSL_CTX_USESUPPORTEDCURVE)
+#define HAVE_SUPPORTED_CURVES
+#endif
+#endif
+
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
@@ -78,38 +110,6 @@ and that's a problem since options.h hasn't been included yet. */
#define CYASSL_MAX_ERROR_SZ 80
#endif
-/* To determine what functions are available we rely on one or both of:
- - the user's options.h generated by CyaSSL/wolfSSL
- - the symbols detected by curl's configure
- Since they are markedly different from one another, and one or the other may
- not be available, we do some checking below to bring things in sync. */
-
-/* HAVE_ALPN is wolfSSL's build time symbol for enabling ALPN in options.h. */
-#ifndef HAVE_ALPN
-#ifdef HAVE_WOLFSSL_USEALPN
-#define HAVE_ALPN
-#endif
-#endif
-
-/* WOLFSSL_ALLOW_SSLV3 is wolfSSL's build time symbol for enabling SSLv3 in
- options.h, but is only seen in >= 3.6.6 since that's when they started
- disabling SSLv3 by default. */
-#ifndef WOLFSSL_ALLOW_SSLV3
-#if (LIBCYASSL_VERSION_HEX < 0x03006006) || \
- defined(HAVE_WOLFSSLV3_CLIENT_METHOD)
-#define WOLFSSL_ALLOW_SSLV3
-#endif
-#endif
-
-/* HAVE_SUPPORTED_CURVES is wolfSSL's build time symbol for enabling the ECC
- supported curve extension in options.h. Note ECC is enabled separately. */
-#ifndef HAVE_SUPPORTED_CURVES
-#if defined(HAVE_CYASSL_CTX_USESUPPORTEDCURVE) || \
- defined(HAVE_WOLFSSL_CTX_USESUPPORTEDCURVE)
-#define HAVE_SUPPORTED_CURVES
-#endif
-#endif
-
static Curl_recv cyassl_recv;
static Curl_send cyassl_send;
diff --git a/Utilities/cmcurl/lib/vtls/darwinssl.c b/Utilities/cmcurl/lib/vtls/darwinssl.c
index 5533dfe2f7..041766541e 100644
--- a/Utilities/cmcurl/lib/vtls/darwinssl.c
+++ b/Utilities/cmcurl/lib/vtls/darwinssl.c
@@ -113,6 +113,36 @@
#define ioErr -36
#define paramErr -50
+#ifdef DARWIN_SSL_PINNEDPUBKEY
+/* both new and old APIs return rsa keys missing the spki header (not DER) */
+static const unsigned char rsa4096SpkiHeader[] = {
+ 0x30, 0x82, 0x02, 0x22, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+ 0x00, 0x03, 0x82, 0x02, 0x0f, 0x00};
+
+static const unsigned char rsa2048SpkiHeader[] = {
+ 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d,
+ 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+ 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05,
+ 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00};
+#ifdef DARWIN_SSL_PINNEDPUBKEY_V1
+/* the *new* version doesn't return DER encoded ecdsa certs like the old... */
+static const unsigned char ecDsaSecp256r1SpkiHeader[] = {
+ 0x30, 0x59, 0x30, 0x13, 0x06, 0x07,
+ 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
+ 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48,
+ 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
+ 0x42, 0x00};
+
+static const unsigned char ecDsaSecp384r1SpkiHeader[] = {
+ 0x30, 0x76, 0x30, 0x10, 0x06, 0x07,
+ 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
+ 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04,
+ 0x00, 0x22, 0x03, 0x62, 0x00};
+#endif /* DARWIN_SSL_PINNEDPUBKEY_V1 */
+#endif /* DARWIN_SSL_PINNEDPUBKEY */
+
/* The following two functions were ripped from Apple sample code,
* with some modifications: */
static OSStatus SocketRead(SSLConnectionRef connection,
@@ -1374,7 +1404,7 @@ static CURLcode darwinssl_connect_step1(struct connectdata *conn,
else
err = CopyIdentityWithLabel(ssl_cert, &cert_and_key);
- if(err == noErr) {
+ if(err == noErr && cert_and_key) {
SecCertificateRef cert = NULL;
CFTypeRef certs_c[1];
CFArrayRef certs;
@@ -1996,6 +2026,112 @@ static int verify_cert(const char *cafile, struct Curl_easy *data,
}
}
+#ifdef DARWIN_SSL_PINNEDPUBKEY
+static CURLcode pkp_pin_peer_pubkey(struct SessionHandle *data,
+ SSLContextRef ctx,
+ const char *pinnedpubkey)
+{ /* Scratch */
+ size_t pubkeylen, realpubkeylen, spkiHeaderLength = 24;
+ unsigned char *pubkey = NULL, *realpubkey = NULL, *spkiHeader = NULL;
+ CFDataRef publicKeyBits = NULL;
+
+ /* Result is returned to caller */
+ CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH;
+
+ /* if a path wasn't specified, don't pin */
+ if(!pinnedpubkey)
+ return CURLE_OK;
+
+
+ if(!ctx)
+ return result;
+
+ do {
+ SecTrustRef trust;
+ OSStatus ret = SSLCopyPeerTrust(ctx, &trust);
+ if(ret != noErr || trust == NULL)
+ break;
+
+ SecKeyRef keyRef = SecTrustCopyPublicKey(trust);
+ CFRelease(trust);
+ if(keyRef == NULL)
+ break;
+
+#ifdef DARWIN_SSL_PINNEDPUBKEY_V1
+
+ publicKeyBits = SecKeyCopyExternalRepresentation(keyRef, NULL);
+ CFRelease(keyRef);
+ if(publicKeyBits == NULL)
+ break;
+
+#elif DARWIN_SSL_PINNEDPUBKEY_V2
+
+ OSStatus success = SecItemExport(keyRef, kSecFormatOpenSSL, 0, NULL,
+ &publicKeyBits);
+ CFRelease(keyRef);
+ if(success != errSecSuccess || publicKeyBits == NULL)
+ break;
+
+#endif /* DARWIN_SSL_PINNEDPUBKEY_V2 */
+
+ pubkeylen = CFDataGetLength(publicKeyBits);
+ pubkey = CFDataGetBytePtr(publicKeyBits);
+
+ switch(pubkeylen) {
+ case 526:
+ /* 4096 bit RSA pubkeylen == 526 */
+ spkiHeader = rsa4096SpkiHeader;
+ break;
+ case 270:
+ /* 2048 bit RSA pubkeylen == 270 */
+ spkiHeader = rsa2048SpkiHeader;
+ break;
+#ifdef DARWIN_SSL_PINNEDPUBKEY_V1
+ case 65:
+ /* ecDSA secp256r1 pubkeylen == 65 */
+ spkiHeader = ecDsaSecp256r1SpkiHeader;
+ spkiHeaderLength = 26;
+ break;
+ case 97:
+ /* ecDSA secp384r1 pubkeylen == 97 */
+ spkiHeader = ecDsaSecp384r1SpkiHeader;
+ spkiHeaderLength = 23;
+ break;
+ default:
+ infof(data, "SSL: unhandled public key length: %d\n", pubkeylen);
+#elif DARWIN_SSL_PINNEDPUBKEY_V2
+ default:
+ /* ecDSA secp256r1 pubkeylen == 91 header already included?
+ * ecDSA secp384r1 header already included too
+ * we assume rest of algorithms do same, so do nothing
+ */
+ result = Curl_pin_peer_pubkey(data, pinnedpubkey, pubkey,
+ pubkeylen);
+#endif /* DARWIN_SSL_PINNEDPUBKEY_V2 */
+ continue; /* break from loop */
+ }
+
+ realpubkeylen = pubkeylen + spkiHeaderLength;
+ realpubkey = malloc(realpubkeylen);
+ if(!realpubkey)
+ break;
+
+ memcpy(realpubkey, spkiHeader, spkiHeaderLength);
+ memcpy(realpubkey + spkiHeaderLength, pubkey, pubkeylen);
+
+ result = Curl_pin_peer_pubkey(data, pinnedpubkey, realpubkey,
+ realpubkeylen);
+
+ } while(0);
+
+ Curl_safefree(realpubkey);
+ if(publicKeyBits != NULL)
+ CFRelease(publicKeyBits);
+
+ return result;
+}
+#endif /* DARWIN_SSL_PINNEDPUBKEY */
+
static CURLcode
darwinssl_connect_step2(struct connectdata *conn, int sockindex)
{
@@ -2102,6 +2238,17 @@ darwinssl_connect_step2(struct connectdata *conn, int sockindex)
/* we have been connected fine, we're not waiting for anything else. */
connssl->connecting_state = ssl_connect_3;
+#ifdef DARWIN_SSL_PINNEDPUBKEY
+ if(data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]) {
+ CURLcode result = pkp_pin_peer_pubkey(data, connssl->ssl_ctx,
+ data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]);
+ if(result) {
+ failf(data, "SSL: public key does not match pinned public key!");
+ return result;
+ }
+ }
+#endif /* DARWIN_SSL_PINNEDPUBKEY */
+
/* Informational message */
(void)SSLGetNegotiatedCipher(connssl->ssl_ctx, &cipher);
(void)SSLGetNegotiatedProtocolVersion(connssl->ssl_ctx, &protocol);
@@ -2573,6 +2720,15 @@ void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
(void)CC_MD5(tmp, (CC_LONG)tmplen, md5sum);
}
+void Curl_darwinssl_sha256sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum, /* output */
+ size_t sha256len)
+{
+ assert(sha256len >= SHA256_DIGEST_LENGTH);
+ (void)CC_SHA256(tmp, (CC_LONG)tmplen, sha256sum);
+}
+
bool Curl_darwinssl_false_start(void)
{
#if CURL_BUILD_MAC_10_9 || CURL_BUILD_IOS_7
diff --git a/Utilities/cmcurl/lib/vtls/darwinssl.h b/Utilities/cmcurl/lib/vtls/darwinssl.h
index 4bd41ca470..fd372ffa09 100644
--- a/Utilities/cmcurl/lib/vtls/darwinssl.h
+++ b/Utilities/cmcurl/lib/vtls/darwinssl.h
@@ -48,11 +48,34 @@ void Curl_darwinssl_md5sum(unsigned char *tmp, /* input */
size_t tmplen,
unsigned char *md5sum, /* output */
size_t md5len);
+void Curl_darwinssl_sha256sum(unsigned char *tmp, /* input */
+ size_t tmplen,
+ unsigned char *sha256sum, /* output */
+ size_t sha256len);
bool Curl_darwinssl_false_start(void);
/* Set the API backend definition to SecureTransport */
#define CURL_SSL_BACKEND CURLSSLBACKEND_DARWINSSL
+/* pinned public key support tests */
+
+/* version 1 supports macOS 10.12+ and iOS 10+ */
+#if ((TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MIN_REQUIRED >= 100000) || \
+ (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200))
+#define DARWIN_SSL_PINNEDPUBKEY_V1 1
+#endif
+
+/* version 2 supports MacOSX 10.7+ */
+#if (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MIN_REQUIRED >= 1070)
+#define DARWIN_SSL_PINNEDPUBKEY_V2 1
+#endif
+
+#if defined(DARWIN_SSL_PINNEDPUBKEY_V1) || defined(DARWIN_SSL_PINNEDPUBKEY_V2)
+/* this backend supports CURLOPT_PINNEDPUBLICKEY */
+#define DARWIN_SSL_PINNEDPUBKEY 1
+#define have_curlssl_pinnedpubkey 1
+#endif /* DARWIN_SSL_PINNEDPUBKEY */
+
/* API setup for SecureTransport */
#define curlssl_init() (1)
#define curlssl_cleanup() Curl_nop_stmt
@@ -70,6 +93,7 @@ bool Curl_darwinssl_false_start(void);
#define curlssl_data_pending(x,y) Curl_darwinssl_data_pending(x, y)
#define curlssl_random(x,y,z) ((void)x, Curl_darwinssl_random(y,z))
#define curlssl_md5sum(a,b,c,d) Curl_darwinssl_md5sum(a,b,c,d)
+#define curlssl_sha256sum(a,b,c,d) Curl_darwinssl_sha256sum(a,b,c,d)
#define curlssl_false_start() Curl_darwinssl_false_start()
#endif /* USE_DARWINSSL */
diff --git a/Utilities/cmcurl/lib/vtls/gtls.c b/Utilities/cmcurl/lib/vtls/gtls.c
index 0230778e2b..844be2de10 100644
--- a/Utilities/cmcurl/lib/vtls/gtls.c
+++ b/Utilities/cmcurl/lib/vtls/gtls.c
@@ -211,18 +211,20 @@ int Curl_gtls_cleanup(void)
return 1;
}
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
static void showtime(struct Curl_easy *data,
const char *text,
time_t stamp)
{
struct tm buffer;
const struct tm *tm = &buffer;
+ char str[96];
CURLcode result = Curl_gmtime(stamp, &buffer);
if(result)
return;
- snprintf(data->state.buffer,
- BUFSIZE,
+ snprintf(str,
+ sizeof(str),
"\t %s: %s, %02d %s %4d %02d:%02d:%02d GMT",
text,
Curl_wkday[tm->tm_wday?tm->tm_wday-1:6],
@@ -232,8 +234,9 @@ static void showtime(struct Curl_easy *data,
tm->tm_hour,
tm->tm_min,
tm->tm_sec);
- infof(data, "%s\n", data->state.buffer);
+ infof(data, "%s\n", str);
}
+#endif
static gnutls_datum_t load_file(const char *file)
{
@@ -962,8 +965,6 @@ gtls_connect_step3(struct connectdata *conn,
gnutls_datum_t issuerp;
char certbuf[256] = ""; /* big enough? */
size_t size;
- unsigned int algo;
- unsigned int bits;
time_t certclock;
const char *ptr;
struct Curl_easy *data = conn->data;
@@ -974,6 +975,8 @@ gtls_connect_step3(struct connectdata *conn,
#endif
CURLcode result = CURLE_OK;
#ifndef CURL_DISABLE_VERBOSE_STRINGS
+ unsigned int algo;
+ unsigned int bits;
gnutls_protocol_t version = gnutls_protocol_get_version(session);
#endif
const char * const hostname = SSL_IS_PROXY() ? conn->http_proxy.host.name :
@@ -1344,6 +1347,7 @@ gtls_connect_step3(struct connectdata *conn,
*/
+#ifndef CURL_DISABLE_VERBOSE_STRINGS
/* public key algorithm's parameters */
algo = gnutls_x509_crt_get_pk_algorithm(x509_cert, &bits);
infof(data, "\t certificate public key: %s\n",
@@ -1368,12 +1372,13 @@ gtls_connect_step3(struct connectdata *conn,
gnutls_x509_crt_get_issuer_dn(x509_cert, certbuf, &size);
infof(data, "\t issuer: %s\n", certbuf);
- gnutls_x509_crt_deinit(x509_cert);
-
/* compression algorithm (if any) */
ptr = gnutls_compression_get_name(gnutls_compression_get(session));
/* the *_get_name() says "NULL" if GNUTLS_COMP_NULL is returned */
infof(data, "\t compression: %s\n", ptr);
+#endif
+
+ gnutls_x509_crt_deinit(x509_cert);
#ifdef HAS_ALPN
if(conn->bits.tls_enable_alpn) {
diff --git a/Utilities/cmcurl/lib/vtls/mbedtls.c b/Utilities/cmcurl/lib/vtls/mbedtls.c
index 3ffa95752c..037babe388 100644
--- a/Utilities/cmcurl/lib/vtls/mbedtls.c
+++ b/Utilities/cmcurl/lib/vtls/mbedtls.c
@@ -67,7 +67,7 @@
#endif
#if defined(THREADING_SUPPORT)
-static mbedtls_entropy_context entropy;
+static mbedtls_entropy_context ts_entropy;
static int entropy_init_initialized = 0;
@@ -131,7 +131,7 @@ static void mbed_debug(void *context, int level, const char *f_name,
/*
* profile
*/
-const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =
+static const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr =
{
/* Hashes from SHA-1 and above */
MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) |
@@ -247,11 +247,11 @@ mbed_connect_step1(struct connectdata *conn,
}
#ifdef THREADING_SUPPORT
- entropy_init_mutex(&entropy);
+ entropy_init_mutex(&ts_entropy);
mbedtls_ctr_drbg_init(&connssl->ctr_drbg);
ret = mbedtls_ctr_drbg_seed(&connssl->ctr_drbg, entropy_func_mutex,
- &entropy, NULL, 0);
+ &ts_entropy, NULL, 0);
if(ret) {
#ifdef MBEDTLS_ERROR_C
mbedtls_strerror(ret, errorbuf, sizeof(errorbuf));
@@ -424,6 +424,11 @@ mbed_connect_step1(struct connectdata *conn,
mbedtls_ssl_conf_ciphersuites(&connssl->config,
mbedtls_ssl_list_ciphersuites());
+#if defined(MBEDTLS_SSL_RENEGOTIATION)
+ mbedtls_ssl_conf_renegotiation(&connssl->config,
+ MBEDTLS_SSL_RENEGOTIATION_ENABLED);
+#endif
+
#if defined(MBEDTLS_SSL_SESSION_TICKETS)
mbedtls_ssl_conf_session_tickets(&connssl->config,
MBEDTLS_SSL_SESSION_TICKETS_DISABLED);
diff --git a/Utilities/cmcurl/lib/vtls/nss.c b/Utilities/cmcurl/lib/vtls/nss.c
index 89a16d3feb..cd01389309 100644
--- a/Utilities/cmcurl/lib/vtls/nss.c
+++ b/Utilities/cmcurl/lib/vtls/nss.c
@@ -81,10 +81,17 @@
static PRLock *nss_initlock = NULL;
static PRLock *nss_crllock = NULL;
static PRLock *nss_findslot_lock = NULL;
+static PRLock *nss_trustload_lock = NULL;
static struct curl_llist nss_crl_list;
static NSSInitContext *nss_context = NULL;
static volatile int initialized = 0;
+/* type used to wrap pointers as list nodes */
+struct ptr_list_wrap {
+ void *ptr;
+ struct curl_llist_element node;
+};
+
typedef struct {
const char *name;
int num;
@@ -201,7 +208,10 @@ static const cipher_s cipherlist[] = {
};
static const char *pem_library = "libnsspem.so";
-static SECMODModule *mod = NULL;
+static SECMODModule *pem_module = NULL;
+
+static const char *trust_library = "libnssckbi.so";
+static SECMODModule *trust_module = NULL;
/* NSPR I/O layer we use to detect blocking direction during SSL handshake */
static PRDescIdentity nspr_io_identity = PR_INVALID_IO_LAYER;
@@ -371,6 +381,18 @@ static PK11SlotInfo* nss_find_slot_by_name(const char *slot_name)
return slot;
}
+/* wrap 'ptr' as list node and tail-insert into 'list' */
+static CURLcode insert_wrapped_ptr(struct curl_llist *list, void *ptr)
+{
+ struct ptr_list_wrap *wrap = malloc(sizeof *wrap);
+ if(!wrap)
+ return CURLE_OUT_OF_MEMORY;
+
+ wrap->ptr = ptr;
+ Curl_llist_insert_next(list, list->tail, wrap, &wrap->node);
+ return CURLE_OK;
+}
+
/* Call PK11_CreateGenericObject() with the given obj_class and filename. If
* the call succeeds, append the object handle to the list of objects so that
* the object can be destroyed in Curl_nss_close(). */
@@ -413,7 +435,7 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl,
if(!obj)
return result;
- if(!Curl_llist_insert_next(&ssl->obj_list, ssl->obj_list.tail, obj)) {
+ if(insert_wrapped_ptr(&ssl->obj_list, obj) != CURLE_OK) {
PK11_DestroyGenericObject(obj);
return CURLE_OUT_OF_MEMORY;
}
@@ -430,17 +452,21 @@ static CURLcode nss_create_object(struct ssl_connect_data *ssl,
* NSS objects in Curl_nss_close() */
static void nss_destroy_object(void *user, void *ptr)
{
- PK11GenericObject *obj = (PK11GenericObject *)ptr;
+ struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr;
+ PK11GenericObject *obj = (PK11GenericObject *) wrap->ptr;
(void) user;
PK11_DestroyGenericObject(obj);
+ free(wrap);
}
/* same as nss_destroy_object() but for CRL items */
static void nss_destroy_crl_item(void *user, void *ptr)
{
- SECItem *crl_der = (SECItem *)ptr;
+ struct ptr_list_wrap *wrap = (struct ptr_list_wrap *) ptr;
+ SECItem *crl_der = (SECItem *) wrap->ptr;
(void) user;
SECITEM_FreeItem(crl_der, PR_TRUE);
+ free(wrap);
}
static CURLcode nss_load_cert(struct ssl_connect_data *ssl,
@@ -496,7 +522,7 @@ static CURLcode nss_cache_crl(SECItem *crl_der)
PR_Lock(nss_crllock);
/* store the CRL item so that we can free it in Curl_nss_cleanup() */
- if(!Curl_llist_insert_next(&nss_crl_list, nss_crl_list.tail, crl_der)) {
+ if(insert_wrapped_ptr(&nss_crl_list, crl_der) != CURLE_OK) {
SECITEM_FreeItem(crl_der, PR_TRUE);
PR_Unlock(nss_crllock);
return CURLE_OUT_OF_MEMORY;
@@ -581,7 +607,7 @@ fail:
static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
char *key_file)
{
- PK11SlotInfo *slot;
+ PK11SlotInfo *slot, *tmp;
SECStatus status;
CURLcode result;
struct ssl_connect_data *ssl = conn->ssl;
@@ -600,7 +626,9 @@ static CURLcode nss_load_key(struct connectdata *conn, int sockindex,
return CURLE_SSL_CERTPROBLEM;
/* This will force the token to be seen as re-inserted */
- SECMOD_WaitForAnyTokenEvent(mod, 0, 0);
+ tmp = SECMOD_WaitForAnyTokenEvent(pem_module, 0, 0);
+ if(tmp)
+ PK11_FreeSlot(tmp);
PK11_IsPresent(slot);
status = PK11_Authenticate(slot, PR_TRUE, SSL_SET_OPTION(key_passwd));
@@ -1178,6 +1206,50 @@ static PRStatus nspr_io_close(PRFileDesc *fd)
return close_fn(fd);
}
+/* load a PKCS #11 module */
+static CURLcode nss_load_module(SECMODModule **pmod, const char *library,
+ const char *name)
+{
+ char *config_string;
+ SECMODModule *module = *pmod;
+ if(module)
+ /* already loaded */
+ return CURLE_OK;
+
+ config_string = aprintf("library=%s name=%s", library, name);
+ if(!config_string)
+ return CURLE_OUT_OF_MEMORY;
+
+ module = SECMOD_LoadUserModule(config_string, NULL, PR_FALSE);
+ free(config_string);
+
+ if(module && module->loaded) {
+ /* loaded successfully */
+ *pmod = module;
+ return CURLE_OK;
+ }
+
+ if(module)
+ SECMOD_DestroyModule(module);
+ return CURLE_FAILED_INIT;
+}
+
+/* unload a PKCS #11 module */
+static void nss_unload_module(SECMODModule **pmod)
+{
+ SECMODModule *module = *pmod;
+ if(!module)
+ /* not loaded */
+ return;
+
+ if(SECMOD_UnloadUserModule(module) != SECSuccess)
+ /* unload failed */
+ return;
+
+ SECMOD_DestroyModule(module);
+ *pmod = NULL;
+}
+
/* data might be NULL */
static CURLcode nss_init_core(struct Curl_easy *data, const char *cert_dir)
{
@@ -1287,6 +1359,7 @@ int Curl_nss_init(void)
nss_initlock = PR_NewLock();
nss_crllock = PR_NewLock();
nss_findslot_lock = PR_NewLock();
+ nss_trustload_lock = PR_NewLock();
}
/* We will actually initialize NSS later */
@@ -1325,10 +1398,8 @@ void Curl_nss_cleanup(void)
* the certificates. */
SSL_ClearSessionCache();
- if(mod && SECSuccess == SECMOD_UnloadUserModule(mod)) {
- SECMOD_DestroyModule(mod);
- mod = NULL;
- }
+ nss_unload_module(&pem_module);
+ nss_unload_module(&trust_module);
NSS_ShutdownContext(nss_context);
nss_context = NULL;
}
@@ -1341,6 +1412,7 @@ void Curl_nss_cleanup(void)
PR_DestroyLock(nss_initlock);
PR_DestroyLock(nss_crllock);
PR_DestroyLock(nss_findslot_lock);
+ PR_DestroyLock(nss_trustload_lock);
nss_initlock = NULL;
initialized = 0;
@@ -1462,12 +1534,44 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
struct Curl_easy *data = conn->data;
const char *cafile = SSL_CONN_CONFIG(CAfile);
const char *capath = SSL_CONN_CONFIG(CApath);
+ bool use_trust_module;
+ CURLcode result = CURLE_OK;
- if(cafile) {
- CURLcode result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
- if(result)
- return result;
+ /* treat empty string as unset */
+ if(cafile && !cafile[0])
+ cafile = NULL;
+ if(capath && !capath[0])
+ capath = NULL;
+
+ infof(data, " CAfile: %s\n CApath: %s\n",
+ cafile ? cafile : "none",
+ capath ? capath : "none");
+
+ /* load libnssckbi.so if no other trust roots were specified */
+ use_trust_module = !cafile && !capath;
+
+ PR_Lock(nss_trustload_lock);
+ if(use_trust_module && !trust_module) {
+ /* libnssckbi.so needed but not yet loaded --> load it! */
+ result = nss_load_module(&trust_module, trust_library, "trust");
+ infof(data, "%s %s\n", (result) ? "failed to load" : "loaded",
+ trust_library);
+ if(result == CURLE_FAILED_INIT)
+ /* make the error non-fatal if we are not going to verify peer */
+ result = CURLE_SSL_CACERT_BADFILE;
}
+ else if(!use_trust_module && trust_module) {
+ /* libnssckbi.so not needed but already loaded --> unload it! */
+ infof(data, "unloading %s\n", trust_library);
+ nss_unload_module(&trust_module);
+ }
+ PR_Unlock(nss_trustload_lock);
+
+ if(cafile)
+ result = nss_load_cert(&conn->ssl[sockindex], cafile, PR_TRUE);
+
+ if(result)
+ return result;
if(capath) {
struct_stat st;
@@ -1501,10 +1605,6 @@ static CURLcode nss_load_ca_certificates(struct connectdata *conn,
infof(data, "warning: CURLOPT_CAPATH not a directory (%s)\n", capath);
}
- infof(data, " CAfile: %s\n CApath: %s\n",
- cafile ? cafile : "none",
- capath ? capath : "none");
-
return CURLE_OK;
}
@@ -1683,29 +1783,17 @@ static CURLcode nss_setup_connect(struct connectdata *conn, int sockindex)
goto error;
}
- result = CURLE_SSL_CONNECT_ERROR;
-
- if(!mod) {
- char *configstring = aprintf("library=%s name=PEM", pem_library);
- if(!configstring) {
- PR_Unlock(nss_initlock);
- goto error;
- }
- mod = SECMOD_LoadUserModule(configstring, NULL, PR_FALSE);
- free(configstring);
-
- if(!mod || !mod->loaded) {
- if(mod) {
- SECMOD_DestroyModule(mod);
- mod = NULL;
- }
- infof(data, "WARNING: failed to load NSS PEM library %s. Using "
- "OpenSSL PEM certificates will not work.\n", pem_library);
- }
- }
-
PK11_SetPasswordFunc(nss_get_password);
+
+ result = nss_load_module(&pem_module, pem_library, "PEM");
PR_Unlock(nss_initlock);
+ if(result == CURLE_FAILED_INIT)
+ infof(data, "WARNING: failed to load NSS PEM library %s. Using "
+ "OpenSSL PEM certificates will not work.\n", pem_library);
+ else if(result)
+ goto error;
+
+ result = CURLE_SSL_CONNECT_ERROR;
model = PR_NewTCPSocket();
if(!model)
diff --git a/Utilities/cmcurl/lib/vtls/openssl.c b/Utilities/cmcurl/lib/vtls/openssl.c
index 58a014a4d7..dbee369297 100644
--- a/Utilities/cmcurl/lib/vtls/openssl.c
+++ b/Utilities/cmcurl/lib/vtls/openssl.c
@@ -236,8 +236,8 @@ static CURLcode Curl_ossl_seed(struct Curl_easy *data)
/* we have the "SSL is seeded" boolean static to prevent multiple
time-consuming seedings in vain */
static bool ssl_seeded = FALSE;
- char *buf = data->state.buffer; /* point to the big buffer */
int nread=0;
+ char fname[256];
if(ssl_seeded)
return CURLE_OK;
@@ -297,11 +297,11 @@ static CURLcode Curl_ossl_seed(struct Curl_easy *data)
} while(!rand_enough());
/* generates a default path for the random seed file */
- buf[0]=0; /* blank it first */
- RAND_file_name(buf, BUFSIZE);
- if(buf[0]) {
+ fname[0]=0; /* blank it first */
+ RAND_file_name(fname, sizeof(fname));
+ if(fname[0]) {
/* we got a file name to try */
- nread += RAND_load_file(buf, RAND_LOAD_LENGTH);
+ nread += RAND_load_file(fname, RAND_LOAD_LENGTH);
if(rand_enough())
return nread;
}
@@ -1371,7 +1371,8 @@ static CURLcode verifystatus(struct connectdata *conn,
st = SSL_CTX_get_cert_store(connssl->ctx);
#if ((OPENSSL_VERSION_NUMBER <= 0x1000201fL) /* Fixed after 1.0.2a */ || \
- defined(LIBRESSL_VERSION_NUMBER))
+ (defined(LIBRESSL_VERSION_NUMBER) && \
+ LIBRESSL_VERSION_NUMBER <= 0x2040200fL))
/* The authorized responder cert in the OCSP response MUST be signed by the
peer cert's issuer (see RFC6960 section 4.2.2.2). If that's a root cert,
no problem, but if it's an intermediate cert OpenSSL has a bug where it
@@ -2807,7 +2808,7 @@ static CURLcode servercert(struct connectdata *conn,
struct Curl_easy *data = conn->data;
X509 *issuer;
FILE *fp;
- char *buffer = data->state.buffer;
+ char buffer[2048];
const char *ptr;
long * const certverifyresult = SSL_IS_PROXY() ?
&data->set.proxy_ssl.certverifyresult : &data->set.ssl.certverifyresult;
@@ -2819,6 +2820,7 @@ static CURLcode servercert(struct connectdata *conn,
connssl->server_cert = SSL_get_peer_certificate(connssl->handle);
if(!connssl->server_cert) {
+ BIO_free(mem);
if(!strict)
return CURLE_OK;
@@ -2829,7 +2831,7 @@ static CURLcode servercert(struct connectdata *conn,
infof(data, "%s certificate:\n", SSL_IS_PROXY() ? "Proxy" : "Server");
rc = x509_name_oneline(X509_get_subject_name(connssl->server_cert),
- buffer, BUFSIZE);
+ buffer, sizeof(buffer));
infof(data, " subject: %s\n", rc?"[NONE]":buffer);
ASN1_TIME_print(mem, X509_get0_notBefore(connssl->server_cert));
@@ -2854,7 +2856,7 @@ static CURLcode servercert(struct connectdata *conn,
}
rc = x509_name_oneline(X509_get_issuer_name(connssl->server_cert),
- buffer, BUFSIZE);
+ buffer, sizeof(buffer));
if(rc) {
if(strict)
failf(data, "SSL: couldn't get X509-issuer name!");
diff --git a/Utilities/cmcurl/lib/vtls/schannel.c b/Utilities/cmcurl/lib/vtls/schannel.c
index c9b513230a..94603018b6 100644
--- a/Utilities/cmcurl/lib/vtls/schannel.c
+++ b/Utilities/cmcurl/lib/vtls/schannel.c
@@ -432,6 +432,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
connssl->recv_unrecoverable_err = CURLE_OK;
connssl->recv_sspi_close_notify = false;
connssl->recv_connection_closed = false;
+ connssl->encdata_is_incomplete = false;
/* continue to second handshake step */
connssl->connecting_state = ssl_connect_2;
@@ -480,6 +481,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
/* buffer to store previously received and encrypted data */
if(connssl->encdata_buffer == NULL) {
+ connssl->encdata_is_incomplete = false;
connssl->encdata_offset = 0;
connssl->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
connssl->encdata_buffer = malloc(connssl->encdata_length);
@@ -532,6 +534,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
/* increase encrypted data buffer offset */
connssl->encdata_offset += nread;
+ connssl->encdata_is_incomplete = false;
+ infof(data, "schannel: encrypted data got %zd\n", nread);
}
infof(data, "schannel: encrypted data buffer: offset %zu length %zu\n",
@@ -576,6 +580,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
/* check if the handshake was incomplete */
if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
+ connssl->encdata_is_incomplete = true;
connssl->connecting_state = ssl_connect_2_reading;
infof(data, "schannel: received incomplete message, need more data\n");
return CURLE_OK;
@@ -625,7 +630,8 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
else
failf(data, "schannel: next InitializeSecurityContext failed: %s",
Curl_sspi_strerror(conn, sspi_status));
- return CURLE_SSL_CONNECT_ERROR;
+ return sspi_status == SEC_E_UNTRUSTED_ROOT ?
+ CURLE_SSL_CACERT_BADFILE : CURLE_SSL_CONNECT_ERROR;
}
/* check if there was additional remaining encrypted data */
@@ -1177,6 +1183,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
}
else if(nread > 0) {
connssl->encdata_offset += (size_t)nread;
+ connssl->encdata_is_incomplete = false;
infof(data, "schannel: encrypted data got %zd\n", nread);
}
}
@@ -1313,6 +1320,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
}
}
else if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
+ connssl->encdata_is_incomplete = true;
if(!*err)
*err = CURLE_AGAIN;
infof(data, "schannel: failed to decrypt data, need more data\n");
@@ -1414,8 +1422,8 @@ bool Curl_schannel_data_pending(const struct connectdata *conn, int sockindex)
const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
if(connssl->use) /* SSL/TLS is in use */
- return (connssl->encdata_offset > 0 ||
- connssl->decdata_offset > 0) ? TRUE : FALSE;
+ return (connssl->decdata_offset > 0 ||
+ (connssl->encdata_offset > 0 && !connssl->encdata_is_incomplete));
else
return FALSE;
}
@@ -1518,6 +1526,7 @@ int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
Curl_safefree(connssl->encdata_buffer);
connssl->encdata_length = 0;
connssl->encdata_offset = 0;
+ connssl->encdata_is_incomplete = false;
}
/* free internal buffer for received decrypted data */
diff --git a/Utilities/cmcurl/lib/x509asn1.c b/Utilities/cmcurl/lib/x509asn1.c
index c4bc7c1fd7..bba20233f2 100644
--- a/Utilities/cmcurl/lib/x509asn1.c
+++ b/Utilities/cmcurl/lib/x509asn1.c
@@ -466,6 +466,7 @@ static const char *GTime2str(const char *beg, const char *end)
break;
case 2:
sec1 = fracp[-2];
+ /* FALLTHROUGH */
case 1:
sec2 = fracp[-1];
break;
diff --git a/Utilities/cmexpat/COPYING b/Utilities/cmexpat/COPYING
index dcb4506429..8d288f0f28 100644
--- a/Utilities/cmexpat/COPYING
+++ b/Utilities/cmexpat/COPYING
@@ -1,6 +1,5 @@
-Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
- and Clark Cooper
-Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Expat maintainers.
+Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper
+Copyright (c) 2001-2017 Expat maintainers
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/Utilities/cmexpat/README b/Utilities/cmexpat/README
index 9ec8d0c6ad..cd11a226c0 100644
--- a/Utilities/cmexpat/README
+++ b/Utilities/cmexpat/README
@@ -1,5 +1,5 @@
- Expat, Release 2.1.1
+ Expat, Release 2.2.1
This is Expat, a C library for parsing XML, written by James Clark.
Expat is a stream-oriented XML parser. This means that you register
@@ -114,7 +114,7 @@ Note for Solaris users: The "ar" command is usually located in
"/usr/ccs/bin", which is not in the default PATH. You will need to
add this to your path for the "make" command, and probably also switch
to GNU make (the "make" found in /usr/ccs/bin does not seem to work
-properly -- appearantly it does not understand .PHONY directives). If
+properly -- apparently it does not understand .PHONY directives). If
you're using ksh or bash, use this command to build:
PATH=/usr/ccs/bin:$PATH make
diff --git a/Utilities/cmexpat/lib/expat.h b/Utilities/cmexpat/lib/expat.h
index 5abcefdfa8..28b0f954d4 100644
--- a/Utilities/cmexpat/lib/expat.h
+++ b/Utilities/cmexpat/lib/expat.h
@@ -95,7 +95,9 @@ enum XML_Error {
/* Added in 2.0. */
XML_ERROR_RESERVED_PREFIX_XML,
XML_ERROR_RESERVED_PREFIX_XMLNS,
- XML_ERROR_RESERVED_NAMESPACE_URI
+ XML_ERROR_RESERVED_NAMESPACE_URI,
+ /* Added in 2.2.1. */
+ XML_ERROR_INVALID_ARGUMENT
};
enum XML_Content_Type {
@@ -342,7 +344,7 @@ XML_SetEntityDeclHandler(XML_Parser parser,
XML_EntityDeclHandler handler);
/* OBSOLETE -- OBSOLETE -- OBSOLETE
- This handler has been superceded by the EntityDeclHandler above.
+ This handler has been superseded by the EntityDeclHandler above.
It is provided here for backward compatibility.
This is called for a declaration of an unparsed (NDATA) entity.
@@ -706,6 +708,7 @@ XML_UseParserAsHandlerArg(XML_Parser parser);
be called, despite an external subset being parsed.
Note: If XML_DTD is not defined when Expat is compiled, returns
XML_ERROR_FEATURE_REQUIRES_XML_DTD.
+ Note: If parser == NULL, returns XML_ERROR_INVALID_ARGUMENT.
*/
XMLPARSEAPI(enum XML_Error)
XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD);
@@ -729,15 +732,16 @@ XML_GetBase(XML_Parser parser);
to the XML_StartElementHandler that were specified in the start-tag
rather than defaulted. Each attribute/value pair counts as 2; thus
this correspondds to an index into the atts array passed to the
- XML_StartElementHandler.
+ XML_StartElementHandler. Returns -1 if parser == NULL.
*/
XMLPARSEAPI(int)
XML_GetSpecifiedAttributeCount(XML_Parser parser);
/* Returns the index of the ID attribute passed in the last call to
- XML_StartElementHandler, or -1 if there is no ID attribute. Each
- attribute/value pair counts as 2; thus this correspondds to an
- index into the atts array passed to the XML_StartElementHandler.
+ XML_StartElementHandler, or -1 if there is no ID attribute or
+ parser == NULL. Each attribute/value pair counts as 2; thus this
+ correspondds to an index into the atts array passed to the
+ XML_StartElementHandler.
*/
XMLPARSEAPI(int)
XML_GetIdAttributeIndex(XML_Parser parser);
@@ -901,6 +905,7 @@ enum XML_ParamEntityParsing {
entities is requested; otherwise it will return non-zero.
Note: If XML_SetParamEntityParsing is called after XML_Parse or
XML_ParseBuffer, then it has no effect and will always return 0.
+ Note: If parser == NULL, the function will do nothing and return 0.
*/
XMLPARSEAPI(int)
XML_SetParamEntityParsing(XML_Parser parser,
@@ -910,6 +915,7 @@ XML_SetParamEntityParsing(XML_Parser parser,
Helps in preventing DoS attacks based on predicting hash
function behavior. This must be called before parsing is started.
Returns 1 if successful, 0 when called after parsing has started.
+ Note: If parser == NULL, the function will do nothing and return 0.
*/
XMLPARSEAPI(int)
XML_SetHashSalt(XML_Parser parser,
@@ -936,6 +942,10 @@ XML_GetErrorCode(XML_Parser parser);
the location is the location of the character at which the error
was detected; otherwise the location is the location of the last
parse event, as described above.
+
+ Note: XML_GetCurrentLineNumber and XML_GetCurrentColumnNumber
+ return 0 to indicate an error.
+ Note: XML_GetCurrentByteIndex returns -1 to indicate an error.
*/
XMLPARSEAPI(XML_Size) XML_GetCurrentLineNumber(XML_Parser parser);
XMLPARSEAPI(XML_Size) XML_GetCurrentColumnNumber(XML_Parser parser);
@@ -1034,13 +1044,11 @@ XMLPARSEAPI(const XML_Feature *)
XML_GetFeatureList(void);
-/* Expat follows the GNU/Linux convention of odd number minor version for
- beta/development releases and even number minor version for stable
- releases. Micro is bumped with each release, and set to 0 with each
- change to major or minor version.
+/* Expat follows the semantic versioning convention.
+ See http://semver.org.
*/
#define XML_MAJOR_VERSION 2
-#define XML_MINOR_VERSION 1
+#define XML_MINOR_VERSION 2
#define XML_MICRO_VERSION 1
#ifdef __cplusplus
diff --git a/Utilities/cmexpat/lib/expat_external.h b/Utilities/cmexpat/lib/expat_external.h
index 07a3c5c8e8..d60eeccfb3 100644
--- a/Utilities/cmexpat/lib/expat_external.h
+++ b/Utilities/cmexpat/lib/expat_external.h
@@ -95,7 +95,10 @@ extern "C" {
#endif
#ifdef XML_UNICODE_WCHAR_T
-#define XML_UNICODE
+# define XML_UNICODE
+# if defined(__SIZEOF_WCHAR_T__) && (__SIZEOF_WCHAR_T__ != 2)
+# error "sizeof(wchar_t) != 2; Need -fshort-wchar for both Expat and libc"
+# endif
#endif
#ifdef XML_UNICODE /* Information is UTF-16 encoded. */
diff --git a/Utilities/cmexpat/lib/siphash.h b/Utilities/cmexpat/lib/siphash.h
new file mode 100644
index 0000000000..db17458083
--- /dev/null
+++ b/Utilities/cmexpat/lib/siphash.h
@@ -0,0 +1,354 @@
+/* ==========================================================================
+ * siphash.h - SipHash-2-4 in a single header file
+ * --------------------------------------------------------------------------
+ * Derived by William Ahern from the reference implementation[1] published[2]
+ * by Jean-Philippe Aumasson and Daniel J. Berstein. Licensed in kind.
+ * by Jean-Philippe Aumasson and Daniel J. Berstein.
+ * Minimal changes by Sebastian Pipping on top, details below.
+ * Licensed under the CC0 Public Domain Dedication license.
+ *
+ * 1. https://www.131002.net/siphash/siphash24.c
+ * 2. https://www.131002.net/siphash/
+ * --------------------------------------------------------------------------
+ * HISTORY:
+ *
+ * 2017-06-10 (Sebastian Pipping)
+ * - Clarify license note in the header
+ * - Address C89 issues:
+ * - Stop using inline keyword (and let compiler decide)
+ * - Turn integer suffix ULL to UL
+ * - Replace _Bool by int
+ * - Turn macro siphash24 into a function
+ * - Address invalid conversion (void pointer) by explicit cast
+ * - Always expose sip24_valid (for self-tests)
+ *
+ * 2012-11-04 - Born. (William Ahern)
+ * --------------------------------------------------------------------------
+ * USAGE:
+ *
+ * SipHash-2-4 takes as input two 64-bit words as the key, some number of
+ * message bytes, and outputs a 64-bit word as the message digest. This
+ * implementation employs two data structures: a struct sipkey for
+ * representing the key, and a struct siphash for representing the hash
+ * state.
+ *
+ * For converting a 16-byte unsigned char array to a key, use either the
+ * macro sip_keyof or the routine sip_tokey. The former instantiates a
+ * compound literal key, while the latter requires a key object as a
+ * parameter.
+ *
+ * unsigned char secret[16];
+ * arc4random_buf(secret, sizeof secret);
+ * struct sipkey *key = sip_keyof(secret);
+ *
+ * For hashing a message, use either the convenience macro siphash24 or the
+ * routines sip24_init, sip24_update, and sip24_final.
+ *
+ * struct siphash state;
+ * void *msg;
+ * size_t len;
+ * uint64_t hash;
+ *
+ * sip24_init(&state, key);
+ * sip24_update(&state, msg, len);
+ * hash = sip24_final(&state);
+ *
+ * or
+ *
+ * hash = siphash24(msg, len, key);
+ *
+ * To convert the 64-bit hash value to a canonical 8-byte little-endian
+ * binary representation, use either the macro sip_binof or the routine
+ * sip_tobin. The former instantiates and returns a compound literal array,
+ * while the latter requires an array object as a parameter.
+ * --------------------------------------------------------------------------
+ * NOTES:
+ *
+ * o Neither sip_keyof, sip_binof, nor siphash24 will work with compilers
+ * lacking compound literal support. Instead, you must use the lower-level
+ * interfaces which take as parameters the temporary state objects.
+ *
+ * o Uppercase macros may evaluate parameters more than once. Lowercase
+ * macros should not exhibit any such side effects.
+ * ==========================================================================
+ */
+#ifndef SIPHASH_H
+#define SIPHASH_H
+
+#include <stddef.h> /* size_t */
+
+#include <cm_kwiml.h>
+
+#ifndef KWIML_INT_HAVE_UINT64_T
+# define uint64_t KWIML_INT_uint64_t
+#endif
+#ifndef KWIML_INT_HAVE_UINT32_T
+# define uint32_t KWIML_INT_uint32_t
+#endif
+#ifndef KWIML_INT_HAVE_UINT8_T
+# define uint8_t KWIML_INT_uint8_t
+#endif
+
+#define SIP_ROTL(x, b) (uint64_t)(((x) << (b)) | ( (x) >> (64 - (b))))
+
+#define SIP_U32TO8_LE(p, v) \
+ (p)[0] = (uint8_t)((v) >> 0); (p)[1] = (uint8_t)((v) >> 8); \
+ (p)[2] = (uint8_t)((v) >> 16); (p)[3] = (uint8_t)((v) >> 24);
+
+#define SIP_U64TO8_LE(p, v) \
+ SIP_U32TO8_LE((p) + 0, (uint32_t)((v) >> 0)); \
+ SIP_U32TO8_LE((p) + 4, (uint32_t)((v) >> 32));
+
+#define SIP_U8TO64_LE(p) \
+ (((uint64_t)((p)[0]) << 0) | \
+ ((uint64_t)((p)[1]) << 8) | \
+ ((uint64_t)((p)[2]) << 16) | \
+ ((uint64_t)((p)[3]) << 24) | \
+ ((uint64_t)((p)[4]) << 32) | \
+ ((uint64_t)((p)[5]) << 40) | \
+ ((uint64_t)((p)[6]) << 48) | \
+ ((uint64_t)((p)[7]) << 56))
+
+
+#define SIPHASH_INITIALIZER { 0, 0, 0, 0, { 0 }, 0, 0 }
+
+struct siphash {
+ uint64_t v0, v1, v2, v3;
+
+ unsigned char buf[8], *p;
+ uint64_t c;
+}; /* struct siphash */
+
+
+#define SIP_KEYLEN 16
+
+struct sipkey {
+ uint64_t k[2];
+}; /* struct sipkey */
+
+#define sip_keyof(k) sip_tokey(&(struct sipkey){ { 0 } }, (k))
+
+static struct sipkey *sip_tokey(struct sipkey *key, const void *src) {
+ key->k[0] = SIP_U8TO64_LE((const unsigned char *)src);
+ key->k[1] = SIP_U8TO64_LE((const unsigned char *)src + 8);
+ return key;
+} /* sip_tokey() */
+
+
+#define sip_binof(v) sip_tobin((unsigned char[8]){ 0 }, (v))
+
+static void *sip_tobin(void *dst, uint64_t u64) {
+ SIP_U64TO8_LE((unsigned char *)dst, u64);
+ return dst;
+} /* sip_tobin() */
+
+
+static void sip_round(struct siphash *H, const int rounds) {
+ int i;
+
+ for (i = 0; i < rounds; i++) {
+ H->v0 += H->v1;
+ H->v1 = SIP_ROTL(H->v1, 13);
+ H->v1 ^= H->v0;
+ H->v0 = SIP_ROTL(H->v0, 32);
+
+ H->v2 += H->v3;
+ H->v3 = SIP_ROTL(H->v3, 16);
+ H->v3 ^= H->v2;
+
+ H->v0 += H->v3;
+ H->v3 = SIP_ROTL(H->v3, 21);
+ H->v3 ^= H->v0;
+
+ H->v2 += H->v1;
+ H->v1 = SIP_ROTL(H->v1, 17);
+ H->v1 ^= H->v2;
+ H->v2 = SIP_ROTL(H->v2, 32);
+ }
+} /* sip_round() */
+
+
+static struct siphash *sip24_init(struct siphash *H, const struct sipkey *key) {
+ H->v0 = 0x736f6d6570736575UL ^ key->k[0];
+ H->v1 = 0x646f72616e646f6dUL ^ key->k[1];
+ H->v2 = 0x6c7967656e657261UL ^ key->k[0];
+ H->v3 = 0x7465646279746573UL ^ key->k[1];
+
+ H->p = H->buf;
+ H->c = 0;
+
+ return H;
+} /* sip24_init() */
+
+
+#define sip_endof(a) (&(a)[sizeof (a) / sizeof *(a)])
+
+static struct siphash *sip24_update(struct siphash *H, const void *src, size_t len) {
+ const unsigned char *p = (const unsigned char *)src, *pe = p + len;
+ uint64_t m;
+
+ do {
+ while (p < pe && H->p < sip_endof(H->buf))
+ *H->p++ = *p++;
+
+ if (H->p < sip_endof(H->buf))
+ break;
+
+ m = SIP_U8TO64_LE(H->buf);
+ H->v3 ^= m;
+ sip_round(H, 2);
+ H->v0 ^= m;
+
+ H->p = H->buf;
+ H->c += 8;
+ } while (p < pe);
+
+ return H;
+} /* sip24_update() */
+
+
+static uint64_t sip24_final(struct siphash *H) {
+ char left = H->p - H->buf;
+ uint64_t b = (H->c + left) << 56;
+
+ switch (left) {
+ case 7: b |= (uint64_t)H->buf[6] << 48;
+ case 6: b |= (uint64_t)H->buf[5] << 40;
+ case 5: b |= (uint64_t)H->buf[4] << 32;
+ case 4: b |= (uint64_t)H->buf[3] << 24;
+ case 3: b |= (uint64_t)H->buf[2] << 16;
+ case 2: b |= (uint64_t)H->buf[1] << 8;
+ case 1: b |= (uint64_t)H->buf[0] << 0;
+ case 0: break;
+ }
+
+ H->v3 ^= b;
+ sip_round(H, 2);
+ H->v0 ^= b;
+ H->v2 ^= 0xff;
+ sip_round(H, 4);
+
+ return H->v0 ^ H->v1 ^ H->v2 ^ H->v3;
+} /* sip24_final() */
+
+
+static uint64_t siphash24(const void *src, size_t len, const struct sipkey *key) {
+ struct siphash state = SIPHASH_INITIALIZER;
+ return sip24_final(sip24_update(sip24_init(&state, key), src, len));
+} /* siphash24() */
+
+
+/*
+ * SipHash-2-4 output with
+ * k = 00 01 02 ...
+ * and
+ * in = (empty string)
+ * in = 00 (1 byte)
+ * in = 00 01 (2 bytes)
+ * in = 00 01 02 (3 bytes)
+ * ...
+ * in = 00 01 02 ... 3e (63 bytes)
+ */
+static int sip24_valid(void) {
+ static const unsigned char vectors[64][8] = {
+ { 0x31, 0x0e, 0x0e, 0xdd, 0x47, 0xdb, 0x6f, 0x72, },
+ { 0xfd, 0x67, 0xdc, 0x93, 0xc5, 0x39, 0xf8, 0x74, },
+ { 0x5a, 0x4f, 0xa9, 0xd9, 0x09, 0x80, 0x6c, 0x0d, },
+ { 0x2d, 0x7e, 0xfb, 0xd7, 0x96, 0x66, 0x67, 0x85, },
+ { 0xb7, 0x87, 0x71, 0x27, 0xe0, 0x94, 0x27, 0xcf, },
+ { 0x8d, 0xa6, 0x99, 0xcd, 0x64, 0x55, 0x76, 0x18, },
+ { 0xce, 0xe3, 0xfe, 0x58, 0x6e, 0x46, 0xc9, 0xcb, },
+ { 0x37, 0xd1, 0x01, 0x8b, 0xf5, 0x00, 0x02, 0xab, },
+ { 0x62, 0x24, 0x93, 0x9a, 0x79, 0xf5, 0xf5, 0x93, },
+ { 0xb0, 0xe4, 0xa9, 0x0b, 0xdf, 0x82, 0x00, 0x9e, },
+ { 0xf3, 0xb9, 0xdd, 0x94, 0xc5, 0xbb, 0x5d, 0x7a, },
+ { 0xa7, 0xad, 0x6b, 0x22, 0x46, 0x2f, 0xb3, 0xf4, },
+ { 0xfb, 0xe5, 0x0e, 0x86, 0xbc, 0x8f, 0x1e, 0x75, },
+ { 0x90, 0x3d, 0x84, 0xc0, 0x27, 0x56, 0xea, 0x14, },
+ { 0xee, 0xf2, 0x7a, 0x8e, 0x90, 0xca, 0x23, 0xf7, },
+ { 0xe5, 0x45, 0xbe, 0x49, 0x61, 0xca, 0x29, 0xa1, },
+ { 0xdb, 0x9b, 0xc2, 0x57, 0x7f, 0xcc, 0x2a, 0x3f, },
+ { 0x94, 0x47, 0xbe, 0x2c, 0xf5, 0xe9, 0x9a, 0x69, },
+ { 0x9c, 0xd3, 0x8d, 0x96, 0xf0, 0xb3, 0xc1, 0x4b, },
+ { 0xbd, 0x61, 0x79, 0xa7, 0x1d, 0xc9, 0x6d, 0xbb, },
+ { 0x98, 0xee, 0xa2, 0x1a, 0xf2, 0x5c, 0xd6, 0xbe, },
+ { 0xc7, 0x67, 0x3b, 0x2e, 0xb0, 0xcb, 0xf2, 0xd0, },
+ { 0x88, 0x3e, 0xa3, 0xe3, 0x95, 0x67, 0x53, 0x93, },
+ { 0xc8, 0xce, 0x5c, 0xcd, 0x8c, 0x03, 0x0c, 0xa8, },
+ { 0x94, 0xaf, 0x49, 0xf6, 0xc6, 0x50, 0xad, 0xb8, },
+ { 0xea, 0xb8, 0x85, 0x8a, 0xde, 0x92, 0xe1, 0xbc, },
+ { 0xf3, 0x15, 0xbb, 0x5b, 0xb8, 0x35, 0xd8, 0x17, },
+ { 0xad, 0xcf, 0x6b, 0x07, 0x63, 0x61, 0x2e, 0x2f, },
+ { 0xa5, 0xc9, 0x1d, 0xa7, 0xac, 0xaa, 0x4d, 0xde, },
+ { 0x71, 0x65, 0x95, 0x87, 0x66, 0x50, 0xa2, 0xa6, },
+ { 0x28, 0xef, 0x49, 0x5c, 0x53, 0xa3, 0x87, 0xad, },
+ { 0x42, 0xc3, 0x41, 0xd8, 0xfa, 0x92, 0xd8, 0x32, },
+ { 0xce, 0x7c, 0xf2, 0x72, 0x2f, 0x51, 0x27, 0x71, },
+ { 0xe3, 0x78, 0x59, 0xf9, 0x46, 0x23, 0xf3, 0xa7, },
+ { 0x38, 0x12, 0x05, 0xbb, 0x1a, 0xb0, 0xe0, 0x12, },
+ { 0xae, 0x97, 0xa1, 0x0f, 0xd4, 0x34, 0xe0, 0x15, },
+ { 0xb4, 0xa3, 0x15, 0x08, 0xbe, 0xff, 0x4d, 0x31, },
+ { 0x81, 0x39, 0x62, 0x29, 0xf0, 0x90, 0x79, 0x02, },
+ { 0x4d, 0x0c, 0xf4, 0x9e, 0xe5, 0xd4, 0xdc, 0xca, },
+ { 0x5c, 0x73, 0x33, 0x6a, 0x76, 0xd8, 0xbf, 0x9a, },
+ { 0xd0, 0xa7, 0x04, 0x53, 0x6b, 0xa9, 0x3e, 0x0e, },
+ { 0x92, 0x59, 0x58, 0xfc, 0xd6, 0x42, 0x0c, 0xad, },
+ { 0xa9, 0x15, 0xc2, 0x9b, 0xc8, 0x06, 0x73, 0x18, },
+ { 0x95, 0x2b, 0x79, 0xf3, 0xbc, 0x0a, 0xa6, 0xd4, },
+ { 0xf2, 0x1d, 0xf2, 0xe4, 0x1d, 0x45, 0x35, 0xf9, },
+ { 0x87, 0x57, 0x75, 0x19, 0x04, 0x8f, 0x53, 0xa9, },
+ { 0x10, 0xa5, 0x6c, 0xf5, 0xdf, 0xcd, 0x9a, 0xdb, },
+ { 0xeb, 0x75, 0x09, 0x5c, 0xcd, 0x98, 0x6c, 0xd0, },
+ { 0x51, 0xa9, 0xcb, 0x9e, 0xcb, 0xa3, 0x12, 0xe6, },
+ { 0x96, 0xaf, 0xad, 0xfc, 0x2c, 0xe6, 0x66, 0xc7, },
+ { 0x72, 0xfe, 0x52, 0x97, 0x5a, 0x43, 0x64, 0xee, },
+ { 0x5a, 0x16, 0x45, 0xb2, 0x76, 0xd5, 0x92, 0xa1, },
+ { 0xb2, 0x74, 0xcb, 0x8e, 0xbf, 0x87, 0x87, 0x0a, },
+ { 0x6f, 0x9b, 0xb4, 0x20, 0x3d, 0xe7, 0xb3, 0x81, },
+ { 0xea, 0xec, 0xb2, 0xa3, 0x0b, 0x22, 0xa8, 0x7f, },
+ { 0x99, 0x24, 0xa4, 0x3c, 0xc1, 0x31, 0x57, 0x24, },
+ { 0xbd, 0x83, 0x8d, 0x3a, 0xaf, 0xbf, 0x8d, 0xb7, },
+ { 0x0b, 0x1a, 0x2a, 0x32, 0x65, 0xd5, 0x1a, 0xea, },
+ { 0x13, 0x50, 0x79, 0xa3, 0x23, 0x1c, 0xe6, 0x60, },
+ { 0x93, 0x2b, 0x28, 0x46, 0xe4, 0xd7, 0x06, 0x66, },
+ { 0xe1, 0x91, 0x5f, 0x5c, 0xb1, 0xec, 0xa4, 0x6c, },
+ { 0xf3, 0x25, 0x96, 0x5c, 0xa1, 0x6d, 0x62, 0x9f, },
+ { 0x57, 0x5f, 0xf2, 0x8e, 0x60, 0x38, 0x1b, 0xe5, },
+ { 0x72, 0x45, 0x06, 0xeb, 0x4c, 0x32, 0x8a, 0x95, }
+ };
+ unsigned char in[64];
+ struct sipkey k;
+ size_t i;
+
+ sip_tokey(&k, "\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017");
+
+ for (i = 0; i < sizeof in; ++i) {
+ in[i] = i;
+
+ if (siphash24(in, i, &k) != SIP_U8TO64_LE(vectors[i]))
+ return 0;
+ }
+
+ return 1;
+} /* sip24_valid() */
+
+
+#if SIPHASH_MAIN
+
+#include <stdio.h>
+
+int main(void) {
+ int ok = sip24_valid();
+
+ if (ok)
+ puts("OK");
+ else
+ puts("FAIL");
+
+ return !ok;
+} /* main() */
+
+#endif /* SIPHASH_MAIN */
+
+
+#endif /* SIPHASH_H */
diff --git a/Utilities/cmexpat/lib/winconfig.h b/Utilities/cmexpat/lib/winconfig.h
index d7dad38f7b..c9dbfea85b 100644
--- a/Utilities/cmexpat/lib/winconfig.h
+++ b/Utilities/cmexpat/lib/winconfig.h
@@ -17,7 +17,24 @@
#include <memory.h>
#include <string.h>
-#include "expat_config.h"
+
+#if defined(HAVE_EXPAT_CONFIG_H) /* e.g. MinGW */
+# include <expat_config.h>
+#else /* !defined(HAVE_EXPAT_CONFIG_H) */
+
+
+#define XML_NS 1
+#define XML_DTD 1
+#define XML_CONTEXT_BYTES 1024
+
+/* we will assume all Windows platforms are little endian */
+#define BYTEORDER 1234
+
+/* Windows has memmove() available. */
+#define HAVE_MEMMOVE
+
+
+#endif /* !defined(HAVE_EXPAT_CONFIG_H) */
#if defined(_MSC_VER)
# pragma warning(push,1)
diff --git a/Utilities/cmexpat/lib/xmlparse.c b/Utilities/cmexpat/lib/xmlparse.c
index b56b66afc2..76f078e250 100644
--- a/Utilities/cmexpat/lib/xmlparse.c
+++ b/Utilities/cmexpat/lib/xmlparse.c
@@ -1,13 +1,19 @@
/* Copyright (c) 1998, 1999, 2000 Thai Open Source Software Center Ltd
See the file COPYING for copying permission.
+
+ 77fea421d361dca90041d0040ecf1dca651167fadf2af79e990e35168d70d933 (2.2.1+)
*/
+#define _GNU_SOURCE /* syscall prototype */
+
#include <stddef.h>
#include <string.h> /* memset(), memcpy() */
#include <assert.h>
#include <limits.h> /* UINT_MAX */
+#include <stdio.h> /* fprintf */
+#include <stdlib.h> /* getenv */
-#ifdef COMPILING_FOR_WINDOWS
+#ifdef _WIN32
#define getpid GetCurrentProcessId
#else
#include <sys/time.h> /* gettimeofday() */
@@ -17,20 +23,15 @@
#define XML_BUILDING_EXPAT 1
-#ifdef COMPILING_FOR_WINDOWS
+#ifdef _WIN32
#include "winconfig.h"
-#elif defined(MACOS_CLASSIC)
-#include "macconfig.h"
-#elif defined(__amigaos__)
-#include "amigaconfig.h"
-#elif defined(__WATCOMC__)
-#include "watcomconfig.h"
#elif defined(HAVE_EXPAT_CONFIG_H)
#include <expat_config.h>
-#endif /* ndef COMPILING_FOR_WINDOWS */
+#endif /* ndef _WIN32 */
#include "ascii.h"
#include "expat.h"
+#include "siphash.h"
#ifdef XML_UNICODE
#define XML_ENCODE_MAX XML_UTF16_ENCODE_MAX
@@ -109,17 +110,11 @@ typedef struct {
const XML_Memory_Handling_Suite *mem;
} HASH_TABLE;
-/* Basic character hash algorithm, taken from Python's string hash:
- h = h * 1000003 ^ character, the constant being a prime number.
+static size_t
+keylen(KEY s);
-*/
-#ifdef XML_UNICODE
-#define CHAR_HASH(h, c) \
- (((h) * 0xF4243) ^ (unsigned short)(c))
-#else
-#define CHAR_HASH(h, c) \
- (((h) * 0xF4243) ^ (unsigned char)(c))
-#endif
+static void
+copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key);
/* For probing (after a collision) we need a step size relative prime
to the hash table size, which is a power of 2. We use double-hashing,
@@ -355,6 +350,8 @@ doIgnoreSection(XML_Parser parser, const ENCODING *, const char **startPtr,
const char *end, const char **nextPtr, XML_Bool haveMore);
#endif /* XML_DTD */
+static void
+freeBindings(XML_Parser parser, BINDING *bindings);
static enum XML_Error
storeAtts(XML_Parser parser, const ENCODING *, const char *s,
TAG_NAME *tagNamePtr, BINDING **bindingsPtr);
@@ -697,10 +694,84 @@ static const XML_Char implicitContext[] = {
ASCII_s, ASCII_p, ASCII_a, ASCII_c, ASCII_e, '\0'
};
+
+#if defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
+# include <errno.h>
+
+# if defined(HAVE_GETRANDOM)
+# include <sys/random.h> /* getrandom */
+# else
+# include <unistd.h> /* syscall */
+# include <sys/syscall.h> /* SYS_getrandom */
+# endif
+
+/* Obtain entropy on Linux 3.17+ */
+static int
+writeRandomBytes_getrandom(void * target, size_t count) {
+ int success = 0; /* full count bytes written? */
+ size_t bytesWrittenTotal = 0;
+ const unsigned int getrandomFlags = 0;
+
+ do {
+ void * const currentTarget = (void*)((char*)target + bytesWrittenTotal);
+ const size_t bytesToWrite = count - bytesWrittenTotal;
+
+ const int bytesWrittenMore =
+#if defined(HAVE_GETRANDOM)
+ getrandom(currentTarget, bytesToWrite, getrandomFlags);
+#else
+ syscall(SYS_getrandom, currentTarget, bytesToWrite, getrandomFlags);
+#endif
+
+ if (bytesWrittenMore > 0) {
+ bytesWrittenTotal += bytesWrittenMore;
+ if (bytesWrittenTotal >= count)
+ success = 1;
+ }
+ } while (! success && (errno == EINTR || errno == EAGAIN));
+
+ return success;
+}
+
+#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM) */
+
+
+#ifdef _WIN32
+
+typedef BOOLEAN (APIENTRY *RTLGENRANDOM_FUNC)(PVOID, ULONG);
+
+/* Obtain entropy on Windows XP / Windows Server 2003 and later.
+ * Hint on RtlGenRandom and the following article from libsodioum.
+ *
+ * Michael Howard: Cryptographically Secure Random number on Windows without using CryptoAPI
+ * https://blogs.msdn.microsoft.com/michael_howard/2005/01/14/cryptographically-secure-random-number-on-windows-without-using-cryptoapi/
+ */
+static int
+writeRandomBytes_RtlGenRandom(void * target, size_t count) {
+ int success = 0; /* full count bytes written? */
+ const HMODULE advapi32 = LoadLibrary("ADVAPI32.DLL");
+
+ if (advapi32) {
+ const RTLGENRANDOM_FUNC RtlGenRandom
+ = (RTLGENRANDOM_FUNC)GetProcAddress(advapi32, "SystemFunction036");
+ if (RtlGenRandom) {
+ if (RtlGenRandom((PVOID)target, (ULONG)count) == TRUE) {
+ success = 1;
+ }
+ }
+ FreeLibrary(advapi32);
+ }
+
+ return success;
+}
+
+#endif /* _WIN32 */
+
+
static unsigned long
gather_time_entropy(void)
{
-#ifdef COMPILING_FOR_WINDOWS
+#ifdef _WIN32
FILETIME ft;
GetSystemTimeAsFileTime(&ft); /* never fails */
return ft.dwHighDateTime ^ ft.dwLowDateTime;
@@ -716,20 +787,62 @@ gather_time_entropy(void)
#endif
}
+#if defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_LIBBSD)
+# include <bsd/stdlib.h>
+#endif
+
+static unsigned long
+ENTROPY_DEBUG(const char * label, unsigned long entropy) {
+ const char * const EXPAT_ENTROPY_DEBUG = getenv("EXPAT_ENTROPY_DEBUG");
+ if (EXPAT_ENTROPY_DEBUG && ! strcmp(EXPAT_ENTROPY_DEBUG, "1")) {
+ fprintf(stderr, "Entropy: %s --> 0x%0*lx (%lu bytes)\n",
+ label,
+ (int)sizeof(entropy) * 2, entropy,
+ (unsigned long)sizeof(entropy));
+ }
+ return entropy;
+}
+
static unsigned long
generate_hash_secret_salt(XML_Parser parser)
{
- /* Process ID is 0 bits entropy if attacker has local access
- * XML_Parser address is few bits of entropy if attacker has local access */
- const unsigned long entropy =
- gather_time_entropy() ^ getpid() ^ (unsigned long)parser;
+ unsigned long entropy;
+ (void)parser;
+#if defined(HAVE_ARC4RANDOM_BUF) || defined(__CloudABI__)
+ (void)gather_time_entropy;
+ arc4random_buf(&entropy, sizeof(entropy));
+ return ENTROPY_DEBUG("arc4random_buf", entropy);
+#else
+ /* Try high quality providers first .. */
+#ifdef _WIN32
+ if (writeRandomBytes_RtlGenRandom((void *)&entropy, sizeof(entropy))) {
+ return ENTROPY_DEBUG("RtlGenRandom", entropy);
+ }
+#elif defined(HAVE_GETRANDOM) || defined(HAVE_SYSCALL_GETRANDOM)
+ if (writeRandomBytes_getrandom((void *)&entropy, sizeof(entropy))) {
+ return ENTROPY_DEBUG("getrandom", entropy);
+ }
+#endif
+ /* .. and self-made low quality for backup: */
+
+ /* Process ID is 0 bits entropy if attacker has local access */
+ entropy = gather_time_entropy() ^ getpid();
/* Factors are 2^31-1 and 2^61-1 (Mersenne primes M31 and M61) */
if (sizeof(unsigned long) == 4) {
- return entropy * 2147483647;
+ return ENTROPY_DEBUG("fallback(4)", entropy * 2147483647);
} else {
- return entropy * 2305843009213693951;
+ return ENTROPY_DEBUG("fallback(8)",
+ entropy * (unsigned long)2305843009213693951);
}
+#endif
+}
+
+static unsigned long
+get_hash_secret_salt(XML_Parser parser) {
+ if (parser->m_parentParser != NULL)
+ return get_hash_secret_salt(parser->m_parentParser);
+ return parser->m_hash_secret_salt;
}
static XML_Bool /* only valid for root parser */
@@ -960,6 +1073,10 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
{
TAG *tStk;
OPEN_INTERNAL_ENTITY *openEntityList;
+
+ if (parser == NULL)
+ return XML_FALSE;
+
if (parentParser)
return XML_FALSE;
/* move tagStack to freeTagList */
@@ -994,6 +1111,8 @@ XML_ParserReset(XML_Parser parser, const XML_Char *encodingName)
enum XML_Status XMLCALL
XML_SetEncoding(XML_Parser parser, const XML_Char *encodingName)
{
+ if (parser == NULL)
+ return XML_STATUS_ERROR;
/* Block after XML_Parse()/XML_ParseBuffer() has been called.
XXX There's no way for the caller to determine which of the
XXX possible error cases caused the XML_STATUS_ERROR return.
@@ -1017,52 +1136,88 @@ XML_ExternalEntityParserCreate(XML_Parser oldParser,
{
XML_Parser parser = oldParser;
DTD *newDtd = NULL;
- DTD *oldDtd = _dtd;
- XML_StartElementHandler oldStartElementHandler = startElementHandler;
- XML_EndElementHandler oldEndElementHandler = endElementHandler;
- XML_CharacterDataHandler oldCharacterDataHandler = characterDataHandler;
- XML_ProcessingInstructionHandler oldProcessingInstructionHandler
- = processingInstructionHandler;
- XML_CommentHandler oldCommentHandler = commentHandler;
- XML_StartCdataSectionHandler oldStartCdataSectionHandler
- = startCdataSectionHandler;
- XML_EndCdataSectionHandler oldEndCdataSectionHandler
- = endCdataSectionHandler;
- XML_DefaultHandler oldDefaultHandler = defaultHandler;
- XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler
- = unparsedEntityDeclHandler;
- XML_NotationDeclHandler oldNotationDeclHandler = notationDeclHandler;
- XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler
- = startNamespaceDeclHandler;
- XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler
- = endNamespaceDeclHandler;
- XML_NotStandaloneHandler oldNotStandaloneHandler = notStandaloneHandler;
- XML_ExternalEntityRefHandler oldExternalEntityRefHandler
- = externalEntityRefHandler;
- XML_SkippedEntityHandler oldSkippedEntityHandler = skippedEntityHandler;
- XML_UnknownEncodingHandler oldUnknownEncodingHandler
- = unknownEncodingHandler;
- XML_ElementDeclHandler oldElementDeclHandler = elementDeclHandler;
- XML_AttlistDeclHandler oldAttlistDeclHandler = attlistDeclHandler;
- XML_EntityDeclHandler oldEntityDeclHandler = entityDeclHandler;
- XML_XmlDeclHandler oldXmlDeclHandler = xmlDeclHandler;
- ELEMENT_TYPE * oldDeclElementType = declElementType;
-
- void *oldUserData = userData;
- void *oldHandlerArg = handlerArg;
- XML_Bool oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
- XML_Parser oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
+ DTD *oldDtd;
+ XML_StartElementHandler oldStartElementHandler;
+ XML_EndElementHandler oldEndElementHandler;
+ XML_CharacterDataHandler oldCharacterDataHandler;
+ XML_ProcessingInstructionHandler oldProcessingInstructionHandler;
+ XML_CommentHandler oldCommentHandler;
+ XML_StartCdataSectionHandler oldStartCdataSectionHandler;
+ XML_EndCdataSectionHandler oldEndCdataSectionHandler;
+ XML_DefaultHandler oldDefaultHandler;
+ XML_UnparsedEntityDeclHandler oldUnparsedEntityDeclHandler;
+ XML_NotationDeclHandler oldNotationDeclHandler;
+ XML_StartNamespaceDeclHandler oldStartNamespaceDeclHandler;
+ XML_EndNamespaceDeclHandler oldEndNamespaceDeclHandler;
+ XML_NotStandaloneHandler oldNotStandaloneHandler;
+ XML_ExternalEntityRefHandler oldExternalEntityRefHandler;
+ XML_SkippedEntityHandler oldSkippedEntityHandler;
+ XML_UnknownEncodingHandler oldUnknownEncodingHandler;
+ XML_ElementDeclHandler oldElementDeclHandler;
+ XML_AttlistDeclHandler oldAttlistDeclHandler;
+ XML_EntityDeclHandler oldEntityDeclHandler;
+ XML_XmlDeclHandler oldXmlDeclHandler;
+ ELEMENT_TYPE * oldDeclElementType;
+
+ void *oldUserData;
+ void *oldHandlerArg;
+ XML_Bool oldDefaultExpandInternalEntities;
+ XML_Parser oldExternalEntityRefHandlerArg;
#ifdef XML_DTD
- enum XML_ParamEntityParsing oldParamEntityParsing = paramEntityParsing;
- int oldInEntityValue = prologState.inEntityValue;
+ enum XML_ParamEntityParsing oldParamEntityParsing;
+ int oldInEntityValue;
#endif
- XML_Bool oldns_triplets = ns_triplets;
+ XML_Bool oldns_triplets;
/* Note that the new parser shares the same hash secret as the old
parser, so that dtdCopy and copyEntityTable can lookup values
from hash tables associated with either parser without us having
to worry which hash secrets each table has.
*/
- unsigned long oldhash_secret_salt = hash_secret_salt;
+ unsigned long oldhash_secret_salt;
+
+ /* Validate the oldParser parameter before we pull everything out of it */
+ if (oldParser == NULL)
+ return NULL;
+
+ /* Stash the original parser contents on the stack */
+ oldDtd = _dtd;
+ oldStartElementHandler = startElementHandler;
+ oldEndElementHandler = endElementHandler;
+ oldCharacterDataHandler = characterDataHandler;
+ oldProcessingInstructionHandler = processingInstructionHandler;
+ oldCommentHandler = commentHandler;
+ oldStartCdataSectionHandler = startCdataSectionHandler;
+ oldEndCdataSectionHandler = endCdataSectionHandler;
+ oldDefaultHandler = defaultHandler;
+ oldUnparsedEntityDeclHandler = unparsedEntityDeclHandler;
+ oldNotationDeclHandler = notationDeclHandler;
+ oldStartNamespaceDeclHandler = startNamespaceDeclHandler;
+ oldEndNamespaceDeclHandler = endNamespaceDeclHandler;
+ oldNotStandaloneHandler = notStandaloneHandler;
+ oldExternalEntityRefHandler = externalEntityRefHandler;
+ oldSkippedEntityHandler = skippedEntityHandler;
+ oldUnknownEncodingHandler = unknownEncodingHandler;
+ oldElementDeclHandler = elementDeclHandler;
+ oldAttlistDeclHandler = attlistDeclHandler;
+ oldEntityDeclHandler = entityDeclHandler;
+ oldXmlDeclHandler = xmlDeclHandler;
+ oldDeclElementType = declElementType;
+
+ oldUserData = userData;
+ oldHandlerArg = handlerArg;
+ oldDefaultExpandInternalEntities = defaultExpandInternalEntities;
+ oldExternalEntityRefHandlerArg = externalEntityRefHandlerArg;
+#ifdef XML_DTD
+ oldParamEntityParsing = paramEntityParsing;
+ oldInEntityValue = prologState.inEntityValue;
+#endif
+ oldns_triplets = ns_triplets;
+ /* Note that the new parser shares the same hash secret as the old
+ parser, so that dtdCopy and copyEntityTable can lookup values
+ from hash tables associated with either parser without us having
+ to worry which hash secrets each table has.
+ */
+ oldhash_secret_salt = hash_secret_salt;
#ifdef XML_DTD
if (!context)
@@ -1228,12 +1383,15 @@ XML_ParserFree(XML_Parser parser)
void XMLCALL
XML_UseParserAsHandlerArg(XML_Parser parser)
{
- handlerArg = parser;
+ if (parser != NULL)
+ handlerArg = parser;
}
enum XML_Error XMLCALL
XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
{
+ if (parser == NULL)
+ return XML_ERROR_INVALID_ARGUMENT;
#ifdef XML_DTD
/* block after XML_Parse()/XML_ParseBuffer() has been called */
if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
@@ -1248,6 +1406,8 @@ XML_UseForeignDTD(XML_Parser parser, XML_Bool useDTD)
void XMLCALL
XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
{
+ if (parser == NULL)
+ return;
/* block after XML_Parse()/XML_ParseBuffer() has been called */
if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
return;
@@ -1257,6 +1417,8 @@ XML_SetReturnNSTriplet(XML_Parser parser, int do_nst)
void XMLCALL
XML_SetUserData(XML_Parser parser, void *p)
{
+ if (parser == NULL)
+ return;
if (handlerArg == userData)
handlerArg = userData = p;
else
@@ -1266,6 +1428,8 @@ XML_SetUserData(XML_Parser parser, void *p)
enum XML_Status XMLCALL
XML_SetBase(XML_Parser parser, const XML_Char *p)
{
+ if (parser == NULL)
+ return XML_STATUS_ERROR;
if (p) {
p = poolCopyString(&_dtd->pool, p);
if (!p)
@@ -1280,18 +1444,24 @@ XML_SetBase(XML_Parser parser, const XML_Char *p)
const XML_Char * XMLCALL
XML_GetBase(XML_Parser parser)
{
+ if (parser == NULL)
+ return NULL;
return curBase;
}
int XMLCALL
XML_GetSpecifiedAttributeCount(XML_Parser parser)
{
+ if (parser == NULL)
+ return -1;
return nSpecifiedAtts;
}
int XMLCALL
XML_GetIdAttributeIndex(XML_Parser parser)
{
+ if (parser == NULL)
+ return -1;
return idAttIndex;
}
@@ -1299,6 +1469,8 @@ XML_GetIdAttributeIndex(XML_Parser parser)
const XML_AttrInfo * XMLCALL
XML_GetAttributeInfo(XML_Parser parser)
{
+ if (parser == NULL)
+ return NULL;
return attInfo;
}
#endif
@@ -1308,6 +1480,8 @@ XML_SetElementHandler(XML_Parser parser,
XML_StartElementHandler start,
XML_EndElementHandler end)
{
+ if (parser == NULL)
+ return;
startElementHandler = start;
endElementHandler = end;
}
@@ -1315,34 +1489,39 @@ XML_SetElementHandler(XML_Parser parser,
void XMLCALL
XML_SetStartElementHandler(XML_Parser parser,
XML_StartElementHandler start) {
- startElementHandler = start;
+ if (parser != NULL)
+ startElementHandler = start;
}
void XMLCALL
XML_SetEndElementHandler(XML_Parser parser,
XML_EndElementHandler end) {
- endElementHandler = end;
+ if (parser != NULL)
+ endElementHandler = end;
}
void XMLCALL
XML_SetCharacterDataHandler(XML_Parser parser,
XML_CharacterDataHandler handler)
{
- characterDataHandler = handler;
+ if (parser != NULL)
+ characterDataHandler = handler;
}
void XMLCALL
XML_SetProcessingInstructionHandler(XML_Parser parser,
XML_ProcessingInstructionHandler handler)
{
- processingInstructionHandler = handler;
+ if (parser != NULL)
+ processingInstructionHandler = handler;
}
void XMLCALL
XML_SetCommentHandler(XML_Parser parser,
XML_CommentHandler handler)
{
- commentHandler = handler;
+ if (parser != NULL)
+ commentHandler = handler;
}
void XMLCALL
@@ -1350,6 +1529,8 @@ XML_SetCdataSectionHandler(XML_Parser parser,
XML_StartCdataSectionHandler start,
XML_EndCdataSectionHandler end)
{
+ if (parser == NULL)
+ return;
startCdataSectionHandler = start;
endCdataSectionHandler = end;
}
@@ -1357,19 +1538,23 @@ XML_SetCdataSectionHandler(XML_Parser parser,
void XMLCALL
XML_SetStartCdataSectionHandler(XML_Parser parser,
XML_StartCdataSectionHandler start) {
- startCdataSectionHandler = start;
+ if (parser != NULL)
+ startCdataSectionHandler = start;
}
void XMLCALL
XML_SetEndCdataSectionHandler(XML_Parser parser,
XML_EndCdataSectionHandler end) {
- endCdataSectionHandler = end;
+ if (parser != NULL)
+ endCdataSectionHandler = end;
}
void XMLCALL
XML_SetDefaultHandler(XML_Parser parser,
XML_DefaultHandler handler)
{
+ if (parser == NULL)
+ return;
defaultHandler = handler;
defaultExpandInternalEntities = XML_FALSE;
}
@@ -1378,6 +1563,8 @@ void XMLCALL
XML_SetDefaultHandlerExpand(XML_Parser parser,
XML_DefaultHandler handler)
{
+ if (parser == NULL)
+ return;
defaultHandler = handler;
defaultExpandInternalEntities = XML_TRUE;
}
@@ -1387,6 +1574,8 @@ XML_SetDoctypeDeclHandler(XML_Parser parser,
XML_StartDoctypeDeclHandler start,
XML_EndDoctypeDeclHandler end)
{
+ if (parser == NULL)
+ return;
startDoctypeDeclHandler = start;
endDoctypeDeclHandler = end;
}
@@ -1394,27 +1583,31 @@ XML_SetDoctypeDeclHandler(XML_Parser parser,
void XMLCALL
XML_SetStartDoctypeDeclHandler(XML_Parser parser,
XML_StartDoctypeDeclHandler start) {
- startDoctypeDeclHandler = start;
+ if (parser != NULL)
+ startDoctypeDeclHandler = start;
}
void XMLCALL
XML_SetEndDoctypeDeclHandler(XML_Parser parser,
XML_EndDoctypeDeclHandler end) {
- endDoctypeDeclHandler = end;
+ if (parser != NULL)
+ endDoctypeDeclHandler = end;
}
void XMLCALL
XML_SetUnparsedEntityDeclHandler(XML_Parser parser,
XML_UnparsedEntityDeclHandler handler)
{
- unparsedEntityDeclHandler = handler;
+ if (parser != NULL)
+ unparsedEntityDeclHandler = handler;
}
void XMLCALL
XML_SetNotationDeclHandler(XML_Parser parser,
XML_NotationDeclHandler handler)
{
- notationDeclHandler = handler;
+ if (parser != NULL)
+ notationDeclHandler = handler;
}
void XMLCALL
@@ -1422,6 +1615,8 @@ XML_SetNamespaceDeclHandler(XML_Parser parser,
XML_StartNamespaceDeclHandler start,
XML_EndNamespaceDeclHandler end)
{
+ if (parser == NULL)
+ return;
startNamespaceDeclHandler = start;
endNamespaceDeclHandler = end;
}
@@ -1429,32 +1624,38 @@ XML_SetNamespaceDeclHandler(XML_Parser parser,
void XMLCALL
XML_SetStartNamespaceDeclHandler(XML_Parser parser,
XML_StartNamespaceDeclHandler start) {
- startNamespaceDeclHandler = start;
+ if (parser != NULL)
+ startNamespaceDeclHandler = start;
}
void XMLCALL
XML_SetEndNamespaceDeclHandler(XML_Parser parser,
XML_EndNamespaceDeclHandler end) {
- endNamespaceDeclHandler = end;
+ if (parser != NULL)
+ endNamespaceDeclHandler = end;
}
void XMLCALL
XML_SetNotStandaloneHandler(XML_Parser parser,
XML_NotStandaloneHandler handler)
{
- notStandaloneHandler = handler;
+ if (parser != NULL)
+ notStandaloneHandler = handler;
}
void XMLCALL
XML_SetExternalEntityRefHandler(XML_Parser parser,
XML_ExternalEntityRefHandler handler)
{
- externalEntityRefHandler = handler;
+ if (parser != NULL)
+ externalEntityRefHandler = handler;
}
void XMLCALL
XML_SetExternalEntityRefHandlerArg(XML_Parser parser, void *arg)
{
+ if (parser == NULL)
+ return;
if (arg)
externalEntityRefHandlerArg = (XML_Parser)arg;
else
@@ -1465,7 +1666,8 @@ void XMLCALL
XML_SetSkippedEntityHandler(XML_Parser parser,
XML_SkippedEntityHandler handler)
{
- skippedEntityHandler = handler;
+ if (parser != NULL)
+ skippedEntityHandler = handler;
}
void XMLCALL
@@ -1473,6 +1675,8 @@ XML_SetUnknownEncodingHandler(XML_Parser parser,
XML_UnknownEncodingHandler handler,
void *data)
{
+ if (parser == NULL)
+ return;
unknownEncodingHandler = handler;
unknownEncodingHandlerData = data;
}
@@ -1481,33 +1685,39 @@ void XMLCALL
XML_SetElementDeclHandler(XML_Parser parser,
XML_ElementDeclHandler eldecl)
{
- elementDeclHandler = eldecl;
+ if (parser != NULL)
+ elementDeclHandler = eldecl;
}
void XMLCALL
XML_SetAttlistDeclHandler(XML_Parser parser,
XML_AttlistDeclHandler attdecl)
{
- attlistDeclHandler = attdecl;
+ if (parser != NULL)
+ attlistDeclHandler = attdecl;
}
void XMLCALL
XML_SetEntityDeclHandler(XML_Parser parser,
XML_EntityDeclHandler handler)
{
- entityDeclHandler = handler;
+ if (parser != NULL)
+ entityDeclHandler = handler;
}
void XMLCALL
XML_SetXmlDeclHandler(XML_Parser parser,
XML_XmlDeclHandler handler) {
- xmlDeclHandler = handler;
+ if (parser != NULL)
+ xmlDeclHandler = handler;
}
int XMLCALL
XML_SetParamEntityParsing(XML_Parser parser,
enum XML_ParamEntityParsing peParsing)
{
+ if (parser == NULL)
+ return 0;
/* block after XML_Parse()/XML_ParseBuffer() has been called */
if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
return 0;
@@ -1523,6 +1733,10 @@ int XMLCALL
XML_SetHashSalt(XML_Parser parser,
unsigned long hash_salt)
{
+ if (parser == NULL)
+ return 0;
+ if (parser->m_parentParser)
+ return XML_SetHashSalt(parser->m_parentParser, hash_salt);
/* block after XML_Parse()/XML_ParseBuffer() has been called */
if (ps_parsing == XML_PARSING || ps_parsing == XML_SUSPENDED)
return 0;
@@ -1533,6 +1747,10 @@ XML_SetHashSalt(XML_Parser parser,
enum XML_Status XMLCALL
XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
{
+ if ((parser == NULL) || (len < 0) || ((s == NULL) && (len != 0))) {
+ errorCode = XML_ERROR_INVALID_ARGUMENT;
+ return XML_STATUS_ERROR;
+ }
switch (ps_parsing) {
case XML_SUSPENDED:
errorCode = XML_ERROR_SUSPENDED;
@@ -1585,6 +1803,13 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
const char *end;
int nLeftOver;
enum XML_Status result;
+ /* Detect overflow (a+b > MAX <==> b > MAX-a) */
+ if (len > ((XML_Size)-1) / 2 - parseEndByteIndex) {
+ errorCode = XML_ERROR_NO_MEMORY;
+ eventPtr = eventEndPtr = NULL;
+ processor = errorProcessor;
+ return XML_STATUS_ERROR;
+ }
parseEndByteIndex += len;
positionPtr = s;
ps_finalBuffer = (XML_Bool)isFinal;
@@ -1617,11 +1842,14 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
nLeftOver = s + len - end;
if (nLeftOver) {
if (buffer == NULL || nLeftOver > bufferLim - buffer) {
- /* FIXME avoid integer overflow */
- char *temp;
- temp = (buffer == NULL
- ? (char *)MALLOC(len * 2)
- : (char *)REALLOC(buffer, len * 2));
+ /* avoid _signed_ integer overflow */
+ char *temp = NULL;
+ const int bytesToAllocate = (int)((unsigned)len * 2U);
+ if (bytesToAllocate > 0) {
+ temp = (buffer == NULL
+ ? (char *)MALLOC(bytesToAllocate)
+ : (char *)REALLOC(buffer, bytesToAllocate));
+ }
if (temp == NULL) {
errorCode = XML_ERROR_NO_MEMORY;
eventPtr = eventEndPtr = NULL;
@@ -1629,7 +1857,7 @@ XML_Parse(XML_Parser parser, const char *s, int len, int isFinal)
return XML_STATUS_ERROR;
}
buffer = temp;
- bufferLim = buffer + len * 2;
+ bufferLim = buffer + bytesToAllocate;
}
memcpy(buffer, end, nLeftOver);
}
@@ -1659,6 +1887,8 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
const char *start;
enum XML_Status result = XML_STATUS_OK;
+ if (parser == NULL)
+ return XML_STATUS_ERROR;
switch (ps_parsing) {
case XML_SUSPENDED:
errorCode = XML_ERROR_SUSPENDED;
@@ -1712,6 +1942,8 @@ XML_ParseBuffer(XML_Parser parser, int len, int isFinal)
void * XMLCALL
XML_GetBuffer(XML_Parser parser, int len)
{
+ if (parser == NULL)
+ return NULL;
if (len < 0) {
errorCode = XML_ERROR_NO_MEMORY;
return NULL;
@@ -1808,6 +2040,8 @@ XML_GetBuffer(XML_Parser parser, int len)
enum XML_Status XMLCALL
XML_StopParser(XML_Parser parser, XML_Bool resumable)
{
+ if (parser == NULL)
+ return XML_STATUS_ERROR;
switch (ps_parsing) {
case XML_SUSPENDED:
if (resumable) {
@@ -1840,6 +2074,8 @@ XML_ResumeParser(XML_Parser parser)
{
enum XML_Status result = XML_STATUS_OK;
+ if (parser == NULL)
+ return XML_STATUS_ERROR;
if (ps_parsing != XML_SUSPENDED) {
errorCode = XML_ERROR_NOT_SUSPENDED;
return XML_STATUS_ERROR;
@@ -1876,6 +2112,8 @@ XML_ResumeParser(XML_Parser parser)
void XMLCALL
XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)
{
+ if (parser == NULL)
+ return;
assert(status != NULL);
*status = parser->m_parsingStatus;
}
@@ -1883,20 +2121,26 @@ XML_GetParsingStatus(XML_Parser parser, XML_ParsingStatus *status)
enum XML_Error XMLCALL
XML_GetErrorCode(XML_Parser parser)
{
+ if (parser == NULL)
+ return XML_ERROR_INVALID_ARGUMENT;
return errorCode;
}
XML_Index XMLCALL
XML_GetCurrentByteIndex(XML_Parser parser)
{
+ if (parser == NULL)
+ return -1;
if (eventPtr)
- return parseEndByteIndex - (parseEndPtr - eventPtr);
+ return (XML_Index)(parseEndByteIndex - (parseEndPtr - eventPtr));
return -1;
}
int XMLCALL
XML_GetCurrentByteCount(XML_Parser parser)
{
+ if (parser == NULL)
+ return 0;
if (eventEndPtr && eventPtr)
return (int)(eventEndPtr - eventPtr);
return 0;
@@ -1906,11 +2150,19 @@ const char * XMLCALL
XML_GetInputContext(XML_Parser parser, int *offset, int *size)
{
#ifdef XML_CONTEXT_BYTES
+ if (parser == NULL)
+ return NULL;
if (eventPtr && buffer) {
- *offset = (int)(eventPtr - buffer);
- *size = (int)(bufferEnd - buffer);
+ if (offset != NULL)
+ *offset = (int)(eventPtr - buffer);
+ if (size != NULL)
+ *size = (int)(bufferEnd - buffer);
return buffer;
}
+#else
+ (void)parser;
+ (void)offset;
+ (void)size;
#endif /* defined XML_CONTEXT_BYTES */
return (char *) 0;
}
@@ -1918,6 +2170,8 @@ XML_GetInputContext(XML_Parser parser, int *offset, int *size)
XML_Size XMLCALL
XML_GetCurrentLineNumber(XML_Parser parser)
{
+ if (parser == NULL)
+ return 0;
if (eventPtr && eventPtr >= positionPtr) {
XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
positionPtr = eventPtr;
@@ -1928,6 +2182,8 @@ XML_GetCurrentLineNumber(XML_Parser parser)
XML_Size XMLCALL
XML_GetCurrentColumnNumber(XML_Parser parser)
{
+ if (parser == NULL)
+ return 0;
if (eventPtr && eventPtr >= positionPtr) {
XmlUpdatePosition(encoding, positionPtr, eventPtr, &position);
positionPtr = eventPtr;
@@ -1938,30 +2194,38 @@ XML_GetCurrentColumnNumber(XML_Parser parser)
void XMLCALL
XML_FreeContentModel(XML_Parser parser, XML_Content *model)
{
- FREE(model);
+ if (parser != NULL)
+ FREE(model);
}
void * XMLCALL
XML_MemMalloc(XML_Parser parser, size_t size)
{
+ if (parser == NULL)
+ return NULL;
return MALLOC(size);
}
void * XMLCALL
XML_MemRealloc(XML_Parser parser, void *ptr, size_t size)
{
+ if (parser == NULL)
+ return NULL;
return REALLOC(ptr, size);
}
void XMLCALL
XML_MemFree(XML_Parser parser, void *ptr)
{
- FREE(ptr);
+ if (parser != NULL)
+ FREE(ptr);
}
void XMLCALL
XML_DefaultCurrent(XML_Parser parser)
{
+ if (parser == NULL)
+ return;
if (defaultHandler) {
if (openInternalEntities)
reportDefault(parser,
@@ -2468,7 +2732,7 @@ doContent(XML_Parser parser,
&fromPtr, rawNameEnd,
(ICHAR **)&toPtr, (ICHAR *)tag->bufEnd - 1);
convLen = (int)(toPtr - (XML_Char *)tag->buf);
- if ((convert_res == XML_CONVERT_COMPLETED) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
+ if ((fromPtr >= rawNameEnd) || (convert_res == XML_CONVERT_INPUT_INCOMPLETE)) {
tag->name.strLen = convLen;
break;
}
@@ -2511,8 +2775,10 @@ doContent(XML_Parser parser,
return XML_ERROR_NO_MEMORY;
poolFinish(&tempPool);
result = storeAtts(parser, enc, s, &name, &bindings);
- if (result)
+ if (result != XML_ERROR_NONE) {
+ freeBindings(parser, bindings);
return result;
+ }
poolFinish(&tempPool);
if (startElementHandler) {
startElementHandler(handlerArg, name.str, (const XML_Char **)atts);
@@ -2527,15 +2793,7 @@ doContent(XML_Parser parser,
if (noElmHandlers && defaultHandler)
reportDefault(parser, enc, s, next);
poolClear(&tempPool);
- while (bindings) {
- BINDING *b = bindings;
- if (endNamespaceDeclHandler)
- endNamespaceDeclHandler(handlerArg, b->prefix->name);
- bindings = bindings->nextTagBinding;
- b->nextTagBinding = freeBindingList;
- freeBindingList = b;
- b->prefix->binding = b->prevPrefixBinding;
- }
+ freeBindings(parser, bindings);
}
if (tagLevel == 0)
return epilogProcessor(parser, next, end, nextPtr);
@@ -2733,6 +2991,29 @@ doContent(XML_Parser parser,
/* not reached */
}
+/* This function does not call free() on the allocated memory, merely
+ * moving it to the parser's freeBindingList where it can be freed or
+ * reused as appropriate.
+ */
+static void
+freeBindings(XML_Parser parser, BINDING *bindings)
+{
+ while (bindings) {
+ BINDING *b = bindings;
+
+ /* startNamespaceDeclHandler will have been called for this
+ * binding in addBindings(), so call the end handler now.
+ */
+ if (endNamespaceDeclHandler)
+ endNamespaceDeclHandler(handlerArg, b->prefix->name);
+
+ bindings = bindings->nextTagBinding;
+ b->nextTagBinding = freeBindingList;
+ freeBindingList = b;
+ b->prefix->binding = b->prevPrefixBinding;
+ }
+}
+
/* Precondition: all arguments must be non-NULL;
Purpose:
- normalize attributes
@@ -2957,7 +3238,13 @@ storeAtts(XML_Parser parser, const ENCODING *enc,
if (s[-1] == 2) { /* prefixed */
ATTRIBUTE_ID *id;
const BINDING *b;
- unsigned long uriHash = hash_secret_salt;
+ unsigned long uriHash;
+ struct siphash sip_state;
+ struct sipkey sip_key;
+
+ copy_salt_to_sipkey(parser, &sip_key);
+ sip24_init(&sip_state, &sip_key);
+
((XML_Char *)s)[-1] = 0; /* clear flag */
id = (ATTRIBUTE_ID *)lookup(parser, &dtd->attributeIds, s, 0);
if (!id || !id->prefix)
@@ -2966,22 +3253,26 @@ storeAtts(XML_Parser parser, const ENCODING *enc,
if (!b)
return XML_ERROR_UNBOUND_PREFIX;
- /* as we expand the name we also calculate its hash value */
for (j = 0; j < b->uriLen; j++) {
const XML_Char c = b->uri[j];
if (!poolAppendChar(&tempPool, c))
return XML_ERROR_NO_MEMORY;
- uriHash = CHAR_HASH(uriHash, c);
}
+
+ sip24_update(&sip_state, b->uri, b->uriLen * sizeof(XML_Char));
+
while (*s++ != XML_T(ASCII_COLON))
;
+
+ sip24_update(&sip_state, s, keylen(s) * sizeof(XML_Char));
+
do { /* copies null terminator */
- const XML_Char c = *s;
if (!poolAppendChar(&tempPool, *s))
return XML_ERROR_NO_MEMORY;
- uriHash = CHAR_HASH(uriHash, c);
} while (*s++);
+ uriHash = (unsigned long)sip24_final(&sip_state);
+
{ /* Check hash table for duplicate of expanded name (uriName).
Derived from code in lookup(parser, HASH_TABLE *table, ...).
*/
@@ -3695,6 +3986,14 @@ entityValueInitProcessor(XML_Parser parser,
*nextPtr = next;
return XML_ERROR_NONE;
}
+ /* If we get this token, we have the start of what might be a
+ normal tag, but not a declaration (i.e. it doesn't begin with
+ "<!"). In a DTD context, that isn't legal.
+ */
+ else if (tok == XML_TOK_INSTANCE_START) {
+ *nextPtr = next;
+ return XML_ERROR_SYNTAX;
+ }
start = next;
eventPtr = start;
}
@@ -4871,6 +5170,8 @@ processInternalEntity(XML_Parser parser, ENTITY *entity,
openEntity->internalEventEndPtr = NULL;
textStart = (char *)entity->textPtr;
textEnd = (char *)(entity->textPtr + entity->textLen);
+ /* Set a safe default value in case 'next' does not get set */
+ next = textStart;
#ifdef XML_DTD
if (entity->is_param) {
@@ -4916,6 +5217,8 @@ internalEntityProcessor(XML_Parser parser,
entity = openEntity->entity;
textStart = ((char *)entity->textPtr) + entity->processed;
textEnd = (char *)(entity->textPtr + entity->textLen);
+ /* Set a safe default value in case 'next' does not get set */
+ next = textStart;
#ifdef XML_DTD
if (entity->is_param) {
@@ -5876,7 +6179,6 @@ dtdCopy(XML_Parser oldParser, DTD *newDtd, const DTD *oldDtd, const XML_Memory_H
newE->defaultAtts = (DEFAULT_ATTRIBUTE *)
ms->malloc_fcn(oldE->nDefaultAtts * sizeof(DEFAULT_ATTRIBUTE));
if (!newE->defaultAtts) {
- ms->free_fcn(newE);
return 0;
}
}
@@ -6011,13 +6313,32 @@ keyeq(KEY s1, KEY s2)
return XML_FALSE;
}
+static size_t
+keylen(KEY s)
+{
+ size_t len = 0;
+ for (; *s; s++, len++);
+ return len;
+}
+
+static void
+copy_salt_to_sipkey(XML_Parser parser, struct sipkey * key)
+{
+ key->k[0] = 0;
+ key->k[1] = get_hash_secret_salt(parser);
+}
+
static unsigned long FASTCALL
hash(XML_Parser parser, KEY s)
{
- unsigned long h = hash_secret_salt;
- while (*s)
- h = CHAR_HASH(h, *s++);
- return h;
+ struct siphash state;
+ struct sipkey key;
+ (void)sip_tobin;
+ (void)sip24_valid;
+ copy_salt_to_sipkey(parser, &key);
+ sip24_init(&state, &key);
+ sip24_update(&state, s, keylen(s) * sizeof(XML_Char));
+ return (unsigned long)sip24_final(&state);
}
static NAMED *
@@ -6260,6 +6581,35 @@ poolStoreString(STRING_POOL *pool, const ENCODING *enc,
return pool->start;
}
+static size_t
+poolBytesToAllocateFor(int blockSize)
+{
+ /* Unprotected math would be:
+ ** return offsetof(BLOCK, s) + blockSize * sizeof(XML_Char);
+ **
+ ** Detect overflow, avoiding _signed_ overflow undefined behavior
+ ** For a + b * c we check b * c in isolation first, so that addition of a
+ ** on top has no chance of making us accept a small non-negative number
+ */
+ const size_t stretch = sizeof(XML_Char); /* can be 4 bytes */
+
+ if (blockSize <= 0)
+ return 0;
+
+ if (blockSize > (int)(INT_MAX / stretch))
+ return 0;
+
+ {
+ const int stretchedBlockSize = blockSize * (int)stretch;
+ const int bytesToAllocate = (int)(
+ offsetof(BLOCK, s) + (unsigned)stretchedBlockSize);
+ if (bytesToAllocate < 0)
+ return 0;
+
+ return (size_t)bytesToAllocate;
+ }
+}
+
static XML_Bool FASTCALL
poolGrow(STRING_POOL *pool)
{
@@ -6289,14 +6639,17 @@ poolGrow(STRING_POOL *pool)
if (pool->blocks && pool->start == pool->blocks->s) {
BLOCK *temp;
int blockSize = (int)((unsigned)(pool->end - pool->start)*2U);
+ size_t bytesToAllocate;
if (blockSize < 0)
return XML_FALSE;
+ bytesToAllocate = poolBytesToAllocateFor(blockSize);
+ if (bytesToAllocate == 0)
+ return XML_FALSE;
+
temp = (BLOCK *)
- pool->mem->realloc_fcn(pool->blocks,
- (offsetof(BLOCK, s)
- + blockSize * sizeof(XML_Char)));
+ pool->mem->realloc_fcn(pool->blocks, (unsigned)bytesToAllocate);
if (temp == NULL)
return XML_FALSE;
pool->blocks = temp;
@@ -6308,16 +6661,26 @@ poolGrow(STRING_POOL *pool)
else {
BLOCK *tem;
int blockSize = (int)(pool->end - pool->start);
+ size_t bytesToAllocate;
if (blockSize < 0)
return XML_FALSE;
if (blockSize < INIT_BLOCK_SIZE)
blockSize = INIT_BLOCK_SIZE;
- else
+ else {
+ /* Detect overflow, avoiding _signed_ overflow undefined behavior */
+ if ((int)((unsigned)blockSize * 2U) < 0) {
+ return XML_FALSE;
+ }
blockSize *= 2;
- tem = (BLOCK *)pool->mem->malloc_fcn(offsetof(BLOCK, s)
- + blockSize * sizeof(XML_Char));
+ }
+
+ bytesToAllocate = poolBytesToAllocateFor(blockSize);
+ if (bytesToAllocate == 0)
+ return XML_FALSE;
+
+ tem = (BLOCK *)pool->mem->malloc_fcn(bytesToAllocate);
if (!tem)
return XML_FALSE;
tem->size = blockSize;
diff --git a/Utilities/cmexpat/lib/xmlrole.c b/Utilities/cmexpat/lib/xmlrole.c
index 4e79ffdfbf..a7c5630279 100644
--- a/Utilities/cmexpat/lib/xmlrole.c
+++ b/Utilities/cmexpat/lib/xmlrole.c
@@ -4,19 +4,13 @@
#include <stddef.h>
-#ifdef COMPILING_FOR_WINDOWS
+#ifdef _WIN32
#include "winconfig.h"
-#elif defined(MACOS_CLASSIC)
-#include "macconfig.h"
-#elif defined(__amigaos__)
-#include "amigaconfig.h"
-#elif defined(__WATCOMC__)
-#include "watcomconfig.h"
#else
#ifdef HAVE_EXPAT_CONFIG_H
#include <expat_config.h>
#endif
-#endif /* ndef COMPILING_FOR_WINDOWS */
+#endif /* ndef _WIN32 */
#include "expat_external.h"
#include "internal.h"
diff --git a/Utilities/cmexpat/lib/xmltok.c b/Utilities/cmexpat/lib/xmltok.c
index 4195279536..cdf0720dd8 100644
--- a/Utilities/cmexpat/lib/xmltok.c
+++ b/Utilities/cmexpat/lib/xmltok.c
@@ -4,19 +4,13 @@
#include <stddef.h>
-#ifdef COMPILING_FOR_WINDOWS
+#ifdef _WIN32
#include "winconfig.h"
-#elif defined(MACOS_CLASSIC)
-#include "macconfig.h"
-#elif defined(__amigaos__)
-#include "amigaconfig.h"
-#elif defined(__WATCOMC__)
-#include "watcomconfig.h"
#else
#ifdef HAVE_EXPAT_CONFIG_H
#include <expat_config.h>
#endif
-#endif /* ndef COMPILING_FOR_WINDOWS */
+#endif /* ndef _WIN32 */
#include "expat_external.h"
#include "internal.h"
@@ -369,24 +363,24 @@ utf8_toUtf8(const ENCODING *UNUSED_P(enc),
const char **fromP, const char *fromLim,
char **toP, const char *toLim)
{
- enum XML_Convert_Result res = XML_CONVERT_COMPLETED;
char *to;
const char *from;
- if (fromLim - *fromP > toLim - *toP) {
- /* Avoid copying partial characters. */
- res = XML_CONVERT_OUTPUT_EXHAUSTED;
- fromLim = *fromP + (toLim - *toP);
- align_limit_to_full_utf8_characters(*fromP, &fromLim);
- }
+ const char *fromLimInitial = fromLim;
+
+ /* Avoid copying partial characters. */
+ align_limit_to_full_utf8_characters(*fromP, &fromLim);
+
for (to = *toP, from = *fromP; (from < fromLim) && (to < toLim); from++, to++)
*to = *from;
*fromP = from;
*toP = to;
- if ((to == toLim) && (from < fromLim))
+ if (fromLim < fromLimInitial)
+ return XML_CONVERT_INPUT_INCOMPLETE;
+ else if ((to == toLim) && (from < fromLim))
return XML_CONVERT_OUTPUT_EXHAUSTED;
else
- return res;
+ return XML_CONVERT_COMPLETED;
}
static enum XML_Convert_Result PTRCALL
@@ -402,7 +396,7 @@ utf8_toUtf16(const ENCODING *enc,
case BT_LEAD2:
if (fromLim - from < 2) {
res = XML_CONVERT_INPUT_INCOMPLETE;
- break;
+ goto after;
}
*to++ = (unsigned short)(((from[0] & 0x1f) << 6) | (from[1] & 0x3f));
from += 2;
@@ -410,7 +404,7 @@ utf8_toUtf16(const ENCODING *enc,
case BT_LEAD3:
if (fromLim - from < 3) {
res = XML_CONVERT_INPUT_INCOMPLETE;
- break;
+ goto after;
}
*to++ = (unsigned short)(((from[0] & 0xf) << 12)
| ((from[1] & 0x3f) << 6) | (from[2] & 0x3f));
@@ -441,6 +435,8 @@ utf8_toUtf16(const ENCODING *enc,
break;
}
}
+ if (from < fromLim)
+ res = XML_CONVERT_OUTPUT_EXHAUSTED;
after:
*fromP = from;
*toP = to;
diff --git a/Utilities/cmexpat/lib/xmltok_impl.c b/Utilities/cmexpat/lib/xmltok_impl.c
index fd0ee222bc..5f779c0571 100644
--- a/Utilities/cmexpat/lib/xmltok_impl.c
+++ b/Utilities/cmexpat/lib/xmltok_impl.c
@@ -1198,6 +1198,8 @@ PREFIX(attributeValueTok)(const ENCODING *enc, const char *ptr,
const char *start;
if (ptr >= end)
return XML_TOK_NONE;
+ else if (! HAS_CHAR(enc, ptr, end))
+ return XML_TOK_PARTIAL;
start = ptr;
while (HAS_CHAR(enc, ptr, end)) {
switch (BYTE_TYPE(enc, ptr)) {
@@ -1256,6 +1258,8 @@ PREFIX(entityValueTok)(const ENCODING *enc, const char *ptr,
const char *start;
if (ptr >= end)
return XML_TOK_NONE;
+ else if (! HAS_CHAR(enc, ptr, end))
+ return XML_TOK_PARTIAL;
start = ptr;
while (HAS_CHAR(enc, ptr, end)) {
switch (BYTE_TYPE(enc, ptr)) {