diff options
67 files changed, 1213 insertions, 122 deletions
diff --git a/Help/command/file.rst b/Help/command/file.rst index 8da46cb..3e669c2 100644 --- a/Help/command/file.rst +++ b/Help/command/file.rst @@ -83,10 +83,12 @@ from the input file. :: - file(<MD5|SHA1|SHA224|SHA256|SHA384|SHA512> <filename> <variable>) + file(<HASH> <filename> <variable>) Compute a cryptographic hash of the content of ``<filename>`` and -store it in a ``<variable>``. +store it in a ``<variable>``. The supported ``<HASH>`` algorithm names +are those listed by the :ref:`string(\<HASH\>) <Supported Hash Algorithms>` +command. ------------------------------------------------------------------------------ @@ -234,8 +236,8 @@ Additional options to ``DOWNLOAD`` are: ``EXPECTED_HASH ALGO=<value>`` Verify that the downloaded content hash matches the expected value, where - ``ALGO`` is one of ``MD5``, ``SHA1``, ``SHA224``, ``SHA256``, ``SHA384``, or - ``SHA512``. If it does not match, the operation fails with an error. + ``ALGO`` is one of the algorithms supported by ``file(<HASH>)``. + If it does not match, the operation fails with an error. ``EXPECTED_MD5 <value>`` Historical short-hand for ``EXPECTED_HASH MD5=<value>``. diff --git a/Help/command/string.rst b/Help/command/string.rst index 8028333..77538f6 100644 --- a/Help/command/string.rst +++ b/Help/command/string.rst @@ -206,15 +206,38 @@ Comparison Compare the strings and store true or false in the output variable. +.. _`Supported Hash Algorithms`: + Hashing ^^^^^^^ :: - string(<MD5|SHA1|SHA224|SHA256|SHA384|SHA512> - <output variable> <input>) + string(<HASH> <output variable> <input>) Compute a cryptographic hash of the input string. +The supported ``<HASH>`` algorithm names are: + +``MD5`` + Message-Digest Algorithm 5, RFC 1321. +``SHA1`` + US Secure Hash Algorithm 1, RFC 3174. +``SHA224`` + US Secure Hash Algorithms, RFC 4634. +``SHA256`` + US Secure Hash Algorithms, RFC 4634. +``SHA384`` + US Secure Hash Algorithms, RFC 4634. +``SHA512`` + US Secure Hash Algorithms, RFC 4634. +``SHA3_224`` + Keccak SHA-3. +``SHA3_256`` + Keccak SHA-3. +``SHA3_384`` + Keccak SHA-3. +``SHA3_512`` + Keccak SHA-3. Generation ^^^^^^^^^^ diff --git a/Help/release/dev/add-SHA-3.rst b/Help/release/dev/add-SHA-3.rst new file mode 100644 index 0000000..5743f10 --- /dev/null +++ b/Help/release/dev/add-SHA-3.rst @@ -0,0 +1,4 @@ +add-SHA-3 +--------- + +* CMake functionality using cryptographic hashes now supports SHA-3 algorithms. diff --git a/Modules/CPack.cmake b/Modules/CPack.cmake index cee1914..4e7546b 100644 --- a/Modules/CPack.cmake +++ b/Modules/CPack.cmake @@ -126,7 +126,9 @@ # # ${CPACK_PACKAGE_FILE_NAME}.${CPACK_PACKAGE_CHECKSUM} # -# Current supported alogorithms: MD5|SHA1|SHA224|SHA256|SHA384|SHA512. +# Supported algorithms are those listed by the +# :ref:`string(\<HASH\>) <Supported Hash Algorithms>` +# command. # # .. variable:: CPACK_PROJECT_CONFIG_FILE # diff --git a/Modules/Compiler/ARMCC.cmake b/Modules/Compiler/ARMCC.cmake index 2ec75c3..250a8f4 100644 --- a/Modules/Compiler/ARMCC.cmake +++ b/Modules/Compiler/ARMCC.cmake @@ -28,6 +28,7 @@ macro(__compiler_armcc lang) set(CMAKE_${lang}_OUTPUT_EXTENSION ".o") set(CMAKE_${lang}_OUTPUT_EXTENSION_REPLACE 1) + set(CMAKE_${lang}_RESPONSE_FILE_LINK_FLAG "--via=") set(CMAKE_${lang}_LINK_EXECUTABLE "<CMAKE_LINKER> <CMAKE_${lang}_LINK_FLAGS> <LINK_FLAGS> <LINK_LIBRARIES> <OBJECTS> -o <TARGET> --list <TARGET_BASE>.map") set(CMAKE_${lang}_CREATE_STATIC_LIBRARY "<CMAKE_AR> --create -cr <TARGET> <LINK_FLAGS> <OBJECTS>") diff --git a/Modules/ExternalData.cmake b/Modules/ExternalData.cmake index 07cd114..873f88d 100644 --- a/Modules/ExternalData.cmake +++ b/Modules/ExternalData.cmake @@ -279,6 +279,10 @@ The following hash algorithms are supported:: SHA256 .sha256 US Secure Hash Algorithms, RFC 4634 SHA384 .sha384 US Secure Hash Algorithms, RFC 4634 SHA512 .sha512 US Secure Hash Algorithms, RFC 4634 + SHA3_224 .sha3-224 Keccak SHA-3 + SHA3_256 .sha3-256 Keccak SHA-3 + SHA3_384 .sha3-384 Keccak SHA-3 + SHA3_512 .sha3-512 Keccak SHA-3 Note that the hashes are used only for unique data identification and download verification. @@ -508,8 +512,8 @@ endfunction() #----------------------------------------------------------------------------- # Private helper interface -set(_ExternalData_REGEX_ALGO "MD5|SHA1|SHA224|SHA256|SHA384|SHA512") -set(_ExternalData_REGEX_EXT "md5|sha1|sha224|sha256|sha384|sha512") +set(_ExternalData_REGEX_ALGO "MD5|SHA1|SHA224|SHA256|SHA384|SHA512|SHA3_224|SHA3_256|SHA3_384|SHA3_512") +set(_ExternalData_REGEX_EXT "md5|sha1|sha224|sha256|sha384|sha512|sha3-224|sha3-256|sha3-384|sha3-512") set(_ExternalData_SELF "${CMAKE_CURRENT_LIST_FILE}") get_filename_component(_ExternalData_SELF_DIR "${_ExternalData_SELF}" PATH) @@ -1082,6 +1086,7 @@ if("${ExternalData_ACTION}" STREQUAL "fetch") if("${ext}" MATCHES "^\\.(${_ExternalData_REGEX_EXT})$") string(TOUPPER "${CMAKE_MATCH_1}" algo) + string(REPLACE "-" "_" algo "${algo}") else() message(FATAL_ERROR "Unknown hash algorithm extension \"${ext}\"") endif() diff --git a/Modules/ExternalProject.cmake b/Modules/ExternalProject.cmake index 1ba4a8f..c20806d 100644 --- a/Modules/ExternalProject.cmake +++ b/Modules/ExternalProject.cmake @@ -427,7 +427,7 @@ if(_ep_func) endif() # Save regex matching supported hash algorithm names. -set(_ep_hash_algos "MD5|SHA1|SHA224|SHA256|SHA384|SHA512") +set(_ep_hash_algos "MD5|SHA1|SHA224|SHA256|SHA384|SHA512|SHA3_224|SHA3_256|SHA3_384|SHA3_512") set(_ep_hash_regex "^(${_ep_hash_algos})=([0-9A-Fa-f]+)$") set(_ExternalProject_SELF "${CMAKE_CURRENT_LIST_FILE}") @@ -2165,12 +2165,12 @@ Update to Mercurial >= 2.1.1. ${uses_terminal} ) - if(always AND update_disconnected) + if(update_disconnected) _ep_get_step_stampfile(${name} skip-update skip-update_stamp_file) string(REPLACE "Performing" "Skipping" comment "${comment}") ExternalProject_Add_Step(${name} skip-update COMMENT ${comment} - ALWAYS 1 + ALWAYS ${always} EXCLUDE_FROM_MAIN 1 WORKING_DIRECTORY ${work_dir} DEPENDEES download diff --git a/Modules/FindBISON.cmake b/Modules/FindBISON.cmake index 5de7a39..d40b806 100644 --- a/Modules/FindBISON.cmake +++ b/Modules/FindBISON.cmake @@ -228,7 +228,7 @@ if(BISON_EXECUTABLE) list(APPEND BISON_TARGET_outputs "${BISON_TARGET_output_header}") add_custom_command(OUTPUT ${BISON_TARGET_outputs} - ${BISON_TARGET_verbose_file} + ${BISON_TARGET_extraoutputs} COMMAND ${BISON_EXECUTABLE} ${BISON_TARGET_cmdopt} -o ${BisonOutput} ${BisonInput} VERBATIM DEPENDS ${BisonInput} diff --git a/Modules/Platform/Windows-MSVC.cmake b/Modules/Platform/Windows-MSVC.cmake index d72ec66..f506500 100644 --- a/Modules/Platform/Windows-MSVC.cmake +++ b/Modules/Platform/Windows-MSVC.cmake @@ -285,13 +285,13 @@ macro(__windows_compiler_msvc lang) # note: MSVC 14 2015 Update 1 sets -fno-ms-compatibility by default, but this does not allow one to compile many projects # that include MS's own headers. CMake itself is affected project too. string(APPEND CMAKE_${lang}_FLAGS_INIT " ${_PLATFORM_DEFINES}${_PLATFORM_DEFINES_${lang}} -fms-extensions -fms-compatibility -D_WINDOWS -Wall${_FLAGS_${lang}}") - string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " -D_DEBUG /MDd -gline-tables-only -fno-inline -O0 ${_RTC1}") + string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " /MDd -gline-tables-only -fno-inline -O0 ${_RTC1}") string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " /MD -O2 -DNDEBUG") string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " /MD -gline-tables-only -O2 -fno-inline -DNDEBUG") string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " /MD -DNDEBUG") # TODO: Add '-Os' once VS generator maps it properly for Clang else() string(APPEND CMAKE_${lang}_FLAGS_INIT " ${_PLATFORM_DEFINES}${_PLATFORM_DEFINES_${lang}} /D_WINDOWS /W3${_FLAGS_${lang}}") - string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " /D_DEBUG /MDd /Zi /Ob0 /Od ${_RTC1}") + string(APPEND CMAKE_${lang}_FLAGS_DEBUG_INIT " /MDd /Zi /Ob0 /Od ${_RTC1}") string(APPEND CMAKE_${lang}_FLAGS_RELEASE_INIT " /MD /O2 /Ob2 /DNDEBUG") string(APPEND CMAKE_${lang}_FLAGS_RELWITHDEBINFO_INIT " /MD /Zi /O2 /Ob1 /DNDEBUG") string(APPEND CMAKE_${lang}_FLAGS_MINSIZEREL_INIT " /MD /O1 /Ob1 /DNDEBUG") diff --git a/Modules/UseSWIG.cmake b/Modules/UseSWIG.cmake index 0e00506..c5912f8 100644 --- a/Modules/UseSWIG.cmake +++ b/Modules/UseSWIG.cmake @@ -10,7 +10,7 @@ # :: # # SWIG_ADD_LIBRARY(<name> -# [TYPE <SHARED|MODULE|STATIC>] +# [TYPE <SHARED|MODULE|STATIC|USE_BUILD_SHARED_LIBS>] # LANGUAGE <language> # SOURCES <file>... # ) @@ -248,6 +248,8 @@ macro(SWIG_ADD_LIBRARY name) if(NOT DEFINED _SAM_TYPE) set(_SAM_TYPE MODULE) + elseif("${_SAM_TYPE}" STREQUAL "USE_BUILD_SHARED_LIBS") + unset(_SAM_TYPE) endif() swig_module_initialize(${name} ${_SAM_LANGUAGE}) diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 718b022..fcda6f9 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -330,6 +330,8 @@ set(SRCS cmOrderDirectories.h cmPolicies.h cmPolicies.cxx + cmProcessOutput.cxx + cmProcessOutput.h cmProcessTools.cxx cmProcessTools.h cmProperty.cxx @@ -632,6 +634,9 @@ set(SRCS cm_codecvt.cxx ) +SET_PROPERTY(SOURCE cmProcessOutput.cxx APPEND PROPERTY COMPILE_DEFINITIONS + KWSYS_ENCODING_DEFAULT_CODEPAGE=${KWSYS_ENCODING_DEFAULT_CODEPAGE}) + # Kdevelop only works on UNIX and not windows if(UNIX) set(SRCS ${SRCS} cmGlobalKdevelopGenerator.cxx) diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index b0c9701..61f621d 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 7) -set(CMake_VERSION_PATCH 20161115) +set(CMake_VERSION_PATCH 20161116) #set(CMake_VERSION_RC 1) diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index 7b4d994..a455908 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -7,6 +7,7 @@ #include "cmFileTimeComparison.h" #include "cmGeneratedFileStream.h" #include "cmMakefile.h" +#include "cmProcessOutput.h" #include "cmSystemTools.h" #include "cmXMLWriter.h" @@ -765,7 +766,7 @@ void cmCTestBuildHandler::LaunchHelper::WriteScrapeMatchers( int cmCTestBuildHandler::RunMakeCommand(const char* command, int* retVal, const char* dir, int timeout, - std::ostream& ofs) + std::ostream& ofs, Encoding encoding) { // First generate the command and arguments std::vector<std::string> args = cmSystemTools::ParseArguments(command); @@ -809,6 +810,8 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command, int* retVal, char* data; int length; + cmProcessOutput processOutput(encoding); + std::string strdata; cmCTestOptionalLog( this->CTest, HANDLER_PROGRESS_OUTPUT, " Each symbol represents " << tick_len << " bytes of output." << std::endl @@ -842,13 +845,25 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command, int* retVal, // Process the chunk of data if (res == cmsysProcess_Pipe_STDERR) { - this->ProcessBuffer(data, length, tick, tick_len, ofs, + processOutput.DecodeText(data, length, strdata, 1); + this->ProcessBuffer(strdata.c_str(), strdata.size(), tick, tick_len, ofs, &this->BuildProcessingErrorQueue); } else { - this->ProcessBuffer(data, length, tick, tick_len, ofs, + processOutput.DecodeText(data, length, strdata, 2); + this->ProcessBuffer(strdata.c_str(), strdata.size(), tick, tick_len, ofs, &this->BuildProcessingQueue); } } + processOutput.DecodeText(std::string(), strdata, 1); + if (!strdata.empty()) { + this->ProcessBuffer(strdata.c_str(), strdata.size(), tick, tick_len, ofs, + &this->BuildProcessingErrorQueue); + } + processOutput.DecodeText(std::string(), strdata, 2); + if (!strdata.empty()) { + this->ProcessBuffer(strdata.c_str(), strdata.size(), tick, tick_len, ofs, + &this->BuildProcessingQueue); + } this->ProcessBuffer(CM_NULLPTR, 0, tick, tick_len, ofs, &this->BuildProcessingQueue); @@ -920,7 +935,7 @@ int cmCTestBuildHandler::RunMakeCommand(const char* command, int* retVal, //###################################################################### //###################################################################### -void cmCTestBuildHandler::ProcessBuffer(const char* data, int length, +void cmCTestBuildHandler::ProcessBuffer(const char* data, size_t length, size_t& tick, size_t tick_len, std::ostream& ofs, t_BuildProcessingQueueType* queue) diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h index 5bd1157..a2f6112 100644 --- a/Source/CTest/cmCTestBuildHandler.h +++ b/Source/CTest/cmCTestBuildHandler.h @@ -7,6 +7,7 @@ #include "cmCTestGenericHandler.h" +#include <cmProcessOutput.h> #include <cmsys/RegularExpression.hxx> #include <deque> #include <iosfwd> @@ -25,6 +26,7 @@ class cmCTestBuildHandler : public cmCTestGenericHandler { public: typedef cmCTestGenericHandler Superclass; + typedef cmProcessOutput::Encoding Encoding; /* * The main entry point for this class @@ -49,7 +51,8 @@ private: //! Run command specialized for make and configure. Returns process status // and retVal is return value or exception. int RunMakeCommand(const char* command, int* retVal, const char* dir, - int timeout, std::ostream& ofs); + int timeout, std::ostream& ofs, + Encoding encoding = cmProcessOutput::Auto); enum { @@ -107,7 +110,7 @@ private: typedef std::deque<char> t_BuildProcessingQueueType; - void ProcessBuffer(const char* data, int length, size_t& tick, + void ProcessBuffer(const char* data, size_t length, size_t& tick, size_t tick_len, std::ostream& ofs, t_BuildProcessingQueueType* queue); int ProcessSingleLine(const char* data); diff --git a/Source/CTest/cmCTestGIT.cxx b/Source/CTest/cmCTestGIT.cxx index 1bc1851..20512ea 100644 --- a/Source/CTest/cmCTestGIT.cxx +++ b/Source/CTest/cmCTestGIT.cxx @@ -91,7 +91,8 @@ std::string cmCTestGIT::FindGitDir() std::string git_dir_line; OneLineParser rev_parse_out(this, "rev-parse-out> ", git_dir_line); OutputLogger rev_parse_err(this->Log, "rev-parse-err> "); - if (this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err)) { + if (this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err, CM_NULLPTR, + cmProcessOutput::UTF8)) { git_dir = git_dir_line; } if (git_dir.empty()) { @@ -114,7 +115,8 @@ std::string cmCTestGIT::FindGitDir() 0 }; OneLineParser cygpath_out(this, "cygpath-out> ", git_dir_line); OutputLogger cygpath_err(this->Log, "cygpath-err> "); - if (this->RunChild(cygpath, &cygpath_out, &cygpath_err)) { + if (this->RunChild(cygpath, &cygpath_out, &cygpath_err, CM_NULLPTR, + cmProcessOutput::UTF8)) { git_dir = git_dir_line; } } @@ -134,7 +136,8 @@ std::string cmCTestGIT::FindTopDir() std::string cdup; OneLineParser rev_parse_out(this, "rev-parse-out> ", cdup); OutputLogger rev_parse_err(this->Log, "rev-parse-err> "); - if (this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err) && + if (this->RunChild(git_rev_parse, &rev_parse_out, &rev_parse_err, CM_NULLPTR, + cmProcessOutput::UTF8) && !cdup.empty()) { top_dir += "/"; top_dir += cdup; @@ -624,7 +627,7 @@ void cmCTestGIT::LoadRevisions() CommitParser out(this, "dt-out> "); OutputLogger err(this->Log, "dt-err> "); - this->RunProcess(cp, &out, &err); + this->RunProcess(cp, &out, &err, cmProcessOutput::UTF8); // Send one extra zero-byte to terminate the last record. out.Process("", 1); @@ -641,14 +644,16 @@ void cmCTestGIT::LoadModifications() CM_NULLPTR }; OutputLogger ui_out(this->Log, "ui-out> "); OutputLogger ui_err(this->Log, "ui-err> "); - this->RunChild(git_update_index, &ui_out, &ui_err); + this->RunChild(git_update_index, &ui_out, &ui_err, CM_NULLPTR, + cmProcessOutput::UTF8); // Use 'git diff-index' to get modified files. const char* git_diff_index[] = { git, "diff-index", "-z", "HEAD", "--", CM_NULLPTR }; DiffParser out(this, "di-out> "); OutputLogger err(this->Log, "di-err> "); - this->RunChild(git_diff_index, &out, &err); + this->RunChild(git_diff_index, &out, &err, CM_NULLPTR, + cmProcessOutput::UTF8); for (std::vector<Change>::const_iterator ci = out.Changes.begin(); ci != out.Changes.end(); ++ci) { diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx index f7a6e0b..43c0fef 100644 --- a/Source/CTest/cmCTestLaunch.cxx +++ b/Source/CTest/cmCTestLaunch.cxx @@ -8,6 +8,7 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmProcessOutput.h" #include "cmStateTypes.h" #include "cmSystemTools.h" #include "cmXMLWriter.h" @@ -225,17 +226,31 @@ void cmCTestLaunch::RunChild() if (!this->Passthru) { char* data = CM_NULLPTR; int length = 0; + cmProcessOutput processOutput; + std::string strdata; while (int p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR)) { if (p == cmsysProcess_Pipe_STDOUT) { - fout.write(data, length); - std::cout.write(data, length); + processOutput.DecodeText(data, length, strdata, 1); + fout.write(strdata.c_str(), strdata.size()); + std::cout.write(strdata.c_str(), strdata.size()); this->HaveOut = true; } else if (p == cmsysProcess_Pipe_STDERR) { - ferr.write(data, length); - std::cerr.write(data, length); + processOutput.DecodeText(data, length, strdata, 2); + ferr.write(strdata.c_str(), strdata.size()); + std::cerr.write(strdata.c_str(), strdata.size()); this->HaveErr = true; } } + processOutput.DecodeText(std::string(), strdata, 1); + if (!strdata.empty()) { + fout.write(strdata.c_str(), strdata.size()); + std::cout.write(strdata.c_str(), strdata.size()); + } + processOutput.DecodeText(std::string(), strdata, 2); + if (!strdata.empty()) { + ferr.write(strdata.c_str(), strdata.size()); + std::cerr.write(strdata.c_str(), strdata.size()); + } } // Wait for the real command to finish. diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 8383132..2b2d207 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -7,6 +7,7 @@ #include "cmCTestScriptHandler.h" #include "cmCurl.h" #include "cmGeneratedFileStream.h" +#include "cmProcessOutput.h" #include "cmState.h" #include "cmStateTypes.h" #include "cmSystemTools.h" @@ -784,10 +785,20 @@ bool cmCTestSubmitHandler::SubmitUsingSCP(const std::string& scp_command, cmsysProcess_Execute(cp); char* data; int length; + cmProcessOutput processOutput; + std::string strdata; while (cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR)) { + processOutput.DecodeText(data, length, strdata); cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, - cmCTestLogWrite(data, length), this->Quiet); + cmCTestLogWrite(strdata.c_str(), strdata.size()), + this->Quiet); + } + processOutput.DecodeText(std::string(), strdata); + if (!strdata.empty()) { + cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + cmCTestLogWrite(strdata.c_str(), strdata.size()), + this->Quiet); } cmsysProcess_WaitForExit(cp, CM_NULLPTR); diff --git a/Source/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx index 7a2fa69..444c43d 100644 --- a/Source/CTest/cmCTestVC.cxx +++ b/Source/CTest/cmCTestVC.cxx @@ -76,7 +76,8 @@ bool cmCTestVC::InitialCheckout(const char* command) } bool cmCTestVC::RunChild(char const* const* cmd, OutputParser* out, - OutputParser* err, const char* workDir) + OutputParser* err, const char* workDir, + Encoding encoding) { this->Log << this->ComputeCommandLine(cmd) << "\n"; @@ -84,7 +85,7 @@ bool cmCTestVC::RunChild(char const* const* cmd, OutputParser* out, cmsysProcess_SetCommand(cp, cmd); workDir = workDir ? workDir : this->SourceDirectory.c_str(); cmsysProcess_SetWorkingDirectory(cp, workDir); - this->RunProcess(cp, out, err); + this->RunProcess(cp, out, err, encoding); int result = cmsysProcess_GetExitValue(cp); cmsysProcess_Delete(cp); return result == 0; @@ -102,7 +103,7 @@ std::string cmCTestVC::ComputeCommandLine(char const* const* cmd) } bool cmCTestVC::RunUpdateCommand(char const* const* cmd, OutputParser* out, - OutputParser* err) + OutputParser* err, Encoding encoding) { // Report the command line. this->UpdateCommandLine = this->ComputeCommandLine(cmd); @@ -112,7 +113,7 @@ bool cmCTestVC::RunUpdateCommand(char const* const* cmd, OutputParser* out, } // Run the command. - return this->RunChild(cmd, out, err); + return this->RunChild(cmd, out, err, CM_NULLPTR, encoding); } std::string cmCTestVC::GetNightlyTime() diff --git a/Source/CTest/cmCTestVC.h b/Source/CTest/cmCTestVC.h index 4f2bba0..dd8b973 100644 --- a/Source/CTest/cmCTestVC.h +++ b/Source/CTest/cmCTestVC.h @@ -116,11 +116,13 @@ protected: /** Run a command line and send output to given parsers. */ bool RunChild(char const* const* cmd, OutputParser* out, OutputParser* err, - const char* workDir = CM_NULLPTR); + const char* workDir = CM_NULLPTR, + Encoding encoding = cmProcessOutput::Auto); /** Run VC update command line and send output to given parsers. */ bool RunUpdateCommand(char const* const* cmd, OutputParser* out, - OutputParser* err = CM_NULLPTR); + OutputParser* err = CM_NULLPTR, + Encoding encoding = cmProcessOutput::Auto); /** Write xml element for one file. */ void WriteXMLEntry(cmXMLWriter& xml, std::string const& path, diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index a24fe21..98bd3bb 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -3,6 +3,7 @@ #include "cmProcess.h" #include <cmConfigure.h> +#include <cmProcessOutput.h> #include <cmSystemTools.h> #include <iostream> @@ -104,6 +105,8 @@ bool cmProcess::Buffer::GetLast(std::string& line) int cmProcess::GetNextOutputLine(std::string& line, double timeout) { + cmProcessOutput processOutput; + std::string strdata; for (;;) { // Look for lines already buffered. if (this->Output.GetLine(line)) { @@ -118,12 +121,17 @@ int cmProcess::GetNextOutputLine(std::string& line, double timeout) return cmsysProcess_Pipe_Timeout; } if (p == cmsysProcess_Pipe_STDOUT) { - this->Output.insert(this->Output.end(), data, data + length); + processOutput.DecodeText(data, length, strdata); + this->Output.insert(this->Output.end(), strdata.begin(), strdata.end()); } else { // p == cmsysProcess_Pipe_None // The process will provide no more data. break; } } + processOutput.DecodeText(std::string(), strdata); + if (!strdata.empty()) { + this->Output.insert(this->Output.end(), strdata.begin(), strdata.end()); + } // Look for partial last lines. if (this->Output.GetLast(line)) { diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index f35a0b3..1527b30 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -41,6 +41,7 @@ #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" +#include "cmProcessOutput.h" #include "cmState.h" #include "cmStateSnapshot.h" #include "cmStateTypes.h" @@ -960,7 +961,7 @@ int cmCTest::GetTestModelFromString(const char* str) int cmCTest::RunMakeCommand(const char* command, std::string& output, int* retVal, const char* dir, int timeout, - std::ostream& ofs) + std::ostream& ofs, Encoding encoding) { // First generate the command and arguments std::vector<std::string> args = cmSystemTools::ParseArguments(command); @@ -999,16 +1000,19 @@ int cmCTest::RunMakeCommand(const char* command, std::string& output, char* data; int length; + cmProcessOutput processOutput(encoding); + std::string strdata; cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, " Each . represents " << tick_len << " bytes of output" << std::endl << " " << std::flush); while (cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR)) { - for (int cc = 0; cc < length; ++cc) { - if (data[cc] == 0) { - data[cc] = '\n'; + processOutput.DecodeText(data, length, strdata); + for (size_t cc = 0; cc < strdata.size(); ++cc) { + if (strdata[cc] == 0) { + strdata[cc] = '\n'; } } - output.append(data, length); + output.append(strdata); while (output.size() > (tick * tick_len)) { tick++; cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, "." << std::flush); @@ -1019,9 +1023,19 @@ int cmCTest::RunMakeCommand(const char* command, std::string& output, << " " << std::flush); } } - cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, cmCTestLogWrite(data, length)); + cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, + cmCTestLogWrite(strdata.c_str(), strdata.size())); + if (ofs) { + ofs << cmCTestLogWrite(strdata.c_str(), strdata.size()); + } + } + processOutput.DecodeText(std::string(), strdata); + if (!strdata.empty()) { + output.append(strdata); + cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, + cmCTestLogWrite(strdata.c_str(), strdata.size())); if (ofs) { - ofs << cmCTestLogWrite(data, length); + ofs << cmCTestLogWrite(strdata.c_str(), strdata.size()); } } cmCTestLog(this, HANDLER_PROGRESS_OUTPUT, " Size of output: " @@ -1061,7 +1075,7 @@ int cmCTest::RunMakeCommand(const char* command, std::string& output, int cmCTest::RunTest(std::vector<const char*> argv, std::string* output, int* retVal, std::ostream* log, double testTimeOut, - std::vector<std::string>* environment) + std::vector<std::string>* environment, Encoding encoding) { bool modifyEnv = (environment && !environment->empty()); @@ -1156,17 +1170,30 @@ int cmCTest::RunTest(std::vector<const char*> argv, std::string* output, char* data; int length; + cmProcessOutput processOutput(encoding); + std::string strdata; while (cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR)) { + processOutput.DecodeText(data, length, strdata); if (output) { tempOutput.insert(tempOutput.end(), data, data + length); } - cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, cmCTestLogWrite(data, length)); + cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, + cmCTestLogWrite(strdata.c_str(), strdata.size())); + if (log) { + log->write(strdata.c_str(), strdata.size()); + } + } + processOutput.DecodeText(std::string(), strdata); + if (!strdata.empty()) { + cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, + cmCTestLogWrite(strdata.c_str(), strdata.size())); if (log) { - log->write(data, length); + log->write(strdata.c_str(), strdata.size()); } } cmsysProcess_WaitForExit(cp, CM_NULLPTR); + processOutput.DecodeText(tempOutput, tempOutput); if (output && tempOutput.begin() != tempOutput.end()) { output->append(&*tempOutput.begin(), tempOutput.size()); } @@ -2496,7 +2523,7 @@ bool cmCTest::SetCTestConfigurationFromCMakeVariable( bool cmCTest::RunCommand(const char* command, std::string* stdOut, std::string* stdErr, int* retVal, const char* dir, - double timeout) + double timeout, Encoding encoding) { std::vector<std::string> args = cmSystemTools::ParseArguments(command); @@ -2527,6 +2554,8 @@ bool cmCTest::RunCommand(const char* command, std::string* stdOut, std::vector<char> tempError; char* data; int length; + cmProcessOutput processOutput(encoding); + std::string strdata; int res; bool done = false; while (!done) { @@ -2543,15 +2572,24 @@ bool cmCTest::RunCommand(const char* command, std::string* stdOut, } if ((res == cmsysProcess_Pipe_STDOUT || res == cmsysProcess_Pipe_STDERR) && this->ExtraVerbose) { - cmSystemTools::Stdout(data, length); + processOutput.DecodeText(data, length, strdata); + cmSystemTools::Stdout(strdata.c_str(), strdata.size()); + } + } + if (this->ExtraVerbose) { + processOutput.DecodeText(std::string(), strdata); + if (!strdata.empty()) { + cmSystemTools::Stdout(strdata.c_str(), strdata.size()); } } cmsysProcess_WaitForExit(cp, CM_NULLPTR); if (!tempOutput.empty()) { + processOutput.DecodeText(tempOutput, tempOutput); stdOut->append(&*tempOutput.begin(), tempOutput.size()); } if (!tempError.empty()) { + processOutput.DecodeText(tempError, tempError); stdErr->append(&*tempError.begin(), tempError.size()); } diff --git a/Source/cmCTest.h b/Source/cmCTest.h index e5b4728..4436327 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -5,6 +5,7 @@ #include <cmConfigure.h> +#include <cmProcessOutput.h> #include <cmsys/String.hxx> #include <map> #include <set> @@ -48,6 +49,7 @@ class cmCTest friend class cmCTestMultiProcessHandler; public: + typedef cmProcessOutput::Encoding Encoding; /** Enumerate parts of the testing and submission process. */ enum Part { @@ -267,7 +269,8 @@ public: */ bool RunCommand(const char* command, std::string* stdOut, std::string* stdErr, int* retVal = CM_NULLPTR, - const char* dir = CM_NULLPTR, double timeout = 0.0); + const char* dir = CM_NULLPTR, double timeout = 0.0, + Encoding encoding = cmProcessOutput::Auto); /** * Clean/make safe for xml the given value such that it may be used as @@ -286,7 +289,8 @@ public: * and retVal is return value or exception. */ int RunMakeCommand(const char* command, std::string& output, int* retVal, - const char* dir, int timeout, std::ostream& ofs); + const char* dir, int timeout, std::ostream& ofs, + Encoding encoding = cmProcessOutput::Auto); /** Return the current tag */ std::string GetCurrentTag(); @@ -333,7 +337,8 @@ public: */ int RunTest(std::vector<const char*> args, std::string* output, int* retVal, std::ostream* logfile, double testTimeOut, - std::vector<std::string>* environment); + std::vector<std::string>* environment, + Encoding encoding = cmProcessOutput::Auto); /** * Execute handler and return its result. If the handler fails, it returns diff --git a/Source/cmCryptoHash.cxx b/Source/cmCryptoHash.cxx index f440999..d5807b1 100644 --- a/Source/cmCryptoHash.cxx +++ b/Source/cmCryptoHash.cxx @@ -9,12 +9,16 @@ static unsigned int const cmCryptoHashAlgoToId[] = { /* clang-format needs this comment to break after the opening brace */ - RHASH_MD5, // - RHASH_SHA1, // - RHASH_SHA224, // - RHASH_SHA256, // - RHASH_SHA384, // - RHASH_SHA512 + RHASH_MD5, // + RHASH_SHA1, // + RHASH_SHA224, // + RHASH_SHA256, // + RHASH_SHA384, // + RHASH_SHA512, // + RHASH_SHA3_224, // + RHASH_SHA3_256, // + RHASH_SHA3_384, // + RHASH_SHA3_512 }; static int cmCryptoHash_rhash_library_initialized; @@ -59,6 +63,18 @@ CM_AUTO_PTR<cmCryptoHash> cmCryptoHash::New(const char* algo) if (strcmp(algo, "SHA512") == 0) { return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA512)); } + if (strcmp(algo, "SHA3_224") == 0) { + return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA3_224)); + } + if (strcmp(algo, "SHA3_256") == 0) { + return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA3_256)); + } + if (strcmp(algo, "SHA3_384") == 0) { + return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA3_384)); + } + if (strcmp(algo, "SHA3_512") == 0) { + return CM_AUTO_PTR<cmCryptoHash>(new cmCryptoHash(AlgoSHA3_512)); + } return CM_AUTO_PTR<cmCryptoHash>(CM_NULLPTR); } diff --git a/Source/cmCryptoHash.h b/Source/cmCryptoHash.h index 95080ac..26d55b3 100644 --- a/Source/cmCryptoHash.h +++ b/Source/cmCryptoHash.h @@ -22,7 +22,11 @@ public: AlgoSHA224, AlgoSHA256, AlgoSHA384, - AlgoSHA512 + AlgoSHA512, + AlgoSHA3_224, + AlgoSHA3_256, + AlgoSHA3_384, + AlgoSHA3_512 }; cmCryptoHash(Algo algo); @@ -30,7 +34,8 @@ public: /// @brief Returns a new hash generator of the requested type /// @arg algo Hash type name. Supported hash types are - /// MD5, SHA1, SHA224, SHA256, SHA384, SHA512 + /// MD5, SHA1, SHA224, SHA256, SHA384, SHA512, + /// SHA3_224, SHA3_256, SHA3_384, SHA3_512 /// @return A valid auto pointer if algo is supported or /// an invalid/NULL pointer otherwise static CM_AUTO_PTR<cmCryptoHash> New(const char* algo); diff --git a/Source/cmExecProgramCommand.cxx b/Source/cmExecProgramCommand.cxx index df92592..6a7292d 100644 --- a/Source/cmExecProgramCommand.cxx +++ b/Source/cmExecProgramCommand.cxx @@ -6,6 +6,7 @@ #include <stdio.h> #include "cmMakefile.h" +#include "cmProcessOutput.h" #include "cmSystemTools.h" class cmExecutionStatus; @@ -116,7 +117,7 @@ bool cmExecProgramCommand::InitialPass(std::vector<std::string> const& args, bool cmExecProgramCommand::RunCommand(const char* command, std::string& output, int& retVal, const char* dir, - bool verbose) + bool verbose, Encoding encoding) { if (cmSystemTools::GetRunCommandOutput()) { verbose = false; @@ -214,17 +215,28 @@ bool cmExecProgramCommand::RunCommand(const char* command, std::string& output, int length; char* data; int p; + cmProcessOutput processOutput(encoding); + std::string strdata; while ((p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR), p)) { if (p == cmsysProcess_Pipe_STDOUT || p == cmsysProcess_Pipe_STDERR) { if (verbose) { - cmSystemTools::Stdout(data, length); + processOutput.DecodeText(data, length, strdata); + cmSystemTools::Stdout(strdata.c_str(), strdata.size()); } output.append(data, length); } } + if (verbose) { + processOutput.DecodeText(std::string(), strdata); + if (!strdata.empty()) { + cmSystemTools::Stdout(strdata.c_str(), strdata.size()); + } + } + // All output has been read. Wait for the process to exit. cmsysProcess_WaitForExit(cp, CM_NULLPTR); + processOutput.DecodeText(output, output); // Check the result of running the process. std::string msg; diff --git a/Source/cmExecProgramCommand.h b/Source/cmExecProgramCommand.h index 7cdf777..58e948e 100644 --- a/Source/cmExecProgramCommand.h +++ b/Source/cmExecProgramCommand.h @@ -8,6 +8,7 @@ #include <vector> #include "cmCommand.h" +#include "cmProcessOutput.h" class cmExecutionStatus; @@ -21,6 +22,7 @@ class cmExecutionStatus; class cmExecProgramCommand : public cmCommand { public: + typedef cmProcessOutput::Encoding Encoding; /** * This is a virtual constructor for the command. */ @@ -46,7 +48,8 @@ public: private: static bool RunCommand(const char* command, std::string& output, int& retVal, const char* directory = CM_NULLPTR, - bool verbose = true); + bool verbose = true, + Encoding encoding = cmProcessOutput::Auto); }; #endif diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx index c8a3a84..1562223 100644 --- a/Source/cmExecuteProcessCommand.cxx +++ b/Source/cmExecuteProcessCommand.cxx @@ -8,6 +8,7 @@ #include <stdio.h> #include "cmMakefile.h" +#include "cmProcessOutput.h" #include "cmSystemTools.h" class cmExecutionStatus; @@ -222,25 +223,43 @@ bool cmExecuteProcessCommand::InitialPass(std::vector<std::string> const& args, int length; char* data; int p; + cmProcessOutput processOutput; + std::string strdata; while ((p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR), p)) { // Put the output in the right place. if (p == cmsysProcess_Pipe_STDOUT && !output_quiet) { if (output_variable.empty()) { - cmSystemTools::Stdout(data, length); + processOutput.DecodeText(data, length, strdata, 1); + cmSystemTools::Stdout(strdata.c_str(), strdata.size()); } else { cmExecuteProcessCommandAppend(tempOutput, data, length); } } else if (p == cmsysProcess_Pipe_STDERR && !error_quiet) { if (error_variable.empty()) { - cmSystemTools::Stderr(data, length); + processOutput.DecodeText(data, length, strdata, 2); + cmSystemTools::Stderr(strdata.c_str(), strdata.size()); } else { cmExecuteProcessCommandAppend(tempError, data, length); } } } + if (!output_quiet && output_variable.empty()) { + processOutput.DecodeText(std::string(), strdata, 1); + if (!strdata.empty()) { + cmSystemTools::Stdout(strdata.c_str(), strdata.size()); + } + } + if (!error_quiet && error_variable.empty()) { + processOutput.DecodeText(std::string(), strdata, 2); + if (!strdata.empty()) { + cmSystemTools::Stderr(strdata.c_str(), strdata.size()); + } + } // All output has been read. Wait for the process to exit. cmsysProcess_WaitForExit(cp, CM_NULLPTR); + processOutput.DecodeText(tempOutput, tempOutput); + processOutput.DecodeText(tempError, tempError); // Fix the text in the output strings. cmExecuteProcessCommandFixText(tempOutput, output_strip_trailing_whitespace); diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 15257fc..c2e37c1 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -111,7 +111,9 @@ bool cmFileCommand::InitialPass(std::vector<std::string> const& args, } if (subCommand == "MD5" || subCommand == "SHA1" || subCommand == "SHA224" || subCommand == "SHA256" || subCommand == "SHA384" || - subCommand == "SHA512") { + subCommand == "SHA512" || subCommand == "SHA3_224" || + subCommand == "SHA3_256" || subCommand == "SHA3_384" || + subCommand == "SHA3_512") { return this->HandleHashCommand(args); } if (subCommand == "STRINGS") { diff --git a/Source/cmFileMonitor.cxx b/Source/cmFileMonitor.cxx index 9844306..03bbf42 100644 --- a/Source/cmFileMonitor.cxx +++ b/Source/cmFileMonitor.cxx @@ -291,7 +291,7 @@ void on_directory_change(uv_fs_event_t* handle, const char* filename, { const cmIBaseWatcher* const watcher = static_cast<const cmIBaseWatcher*>(handle->data); - const std::string pathSegment(filename); + const std::string pathSegment(filename ? filename : ""); watcher->Trigger(pathSegment, events, status); } diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index e7dfed5..1fda4e9 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -211,7 +211,14 @@ void cmLocalGenerator::TraceDependencies() void cmLocalGenerator::GenerateTestFiles() { + std::string file = this->StateSnapshot.GetDirectory().GetCurrentBinary(); + file += "/"; + file += "CTestTestfile.cmake"; + if (!this->Makefile->IsOn("CMAKE_TESTING_ENABLED")) { + if (cmSystemTools::FileExists(file)) { + cmSystemTools::RemoveFile(file); + } return; } @@ -220,10 +227,6 @@ void cmLocalGenerator::GenerateTestFiles() const std::string& config = this->Makefile->GetConfigurations(configurationTypes, false); - std::string file = this->StateSnapshot.GetDirectory().GetCurrentBinary(); - file += "/"; - file += "CTestTestfile.cmake"; - cmGeneratedFileStream fout(file.c_str()); fout.SetCopyIfDifferent(true); diff --git a/Source/cmProcessOutput.cxx b/Source/cmProcessOutput.cxx new file mode 100644 index 0000000..1440223 --- /dev/null +++ b/Source/cmProcessOutput.cxx @@ -0,0 +1,155 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmProcessOutput.h" + +#if defined(_WIN32) +#include <windows.h> +unsigned int cmProcessOutput::defaultCodepage = + KWSYS_ENCODING_DEFAULT_CODEPAGE; +#endif + +cmProcessOutput::cmProcessOutput(Encoding encoding, unsigned int maxSize) +{ +#if defined(_WIN32) + codepage = 0; + bufferSize = maxSize; + if (encoding == None) { + codepage = defaultCodepage; + } else if (encoding == Auto) { + codepage = GetConsoleCP(); + } else if (encoding == UTF8) { + codepage = CP_UTF8; + } else if (encoding == OEM) { + codepage = GetOEMCP(); + } + if (!codepage || encoding == ANSI) { + codepage = GetACP(); + } +#else + static_cast<void>(encoding); + static_cast<void>(maxSize); +#endif +} + +cmProcessOutput::~cmProcessOutput() +{ +} + +bool cmProcessOutput::DecodeText(std::string raw, std::string& decoded, + size_t id) +{ + bool success = true; + decoded = raw; +#if defined(_WIN32) + if (id > 0) { + if (rawparts.size() < id) { + rawparts.reserve(id); + while (rawparts.size() < id) + rawparts.push_back(std::string()); + } + raw = rawparts[id - 1] + raw; + rawparts[id - 1].clear(); + decoded = raw; + } + if (raw.size() > 0 && codepage != defaultCodepage) { + success = false; + CPINFOEXW cpinfo; + if (id > 0 && bufferSize > 0 && raw.size() == bufferSize && + GetCPInfoExW(codepage, 0, &cpinfo) == 1 && cpinfo.MaxCharSize > 1) { + if (cpinfo.MaxCharSize == 2 && cpinfo.LeadByte[0] != 0) { + LPSTR prevChar = + CharPrevExA(codepage, raw.c_str(), raw.c_str() + raw.size(), 0); + bool isLeadByte = + (*(prevChar + 1) == 0) && IsDBCSLeadByteEx(codepage, *prevChar); + if (isLeadByte) { + rawparts[id - 1] += *(raw.end() - 1); + raw.resize(raw.size() - 1); + } + success = DoDecodeText(raw, decoded, NULL); + } else { + bool restoreDecoded = false; + std::string firstDecoded = decoded; + wchar_t lastChar = 0; + for (UINT i = 0; i < cpinfo.MaxCharSize; i++) { + success = DoDecodeText(raw, decoded, &lastChar); + if (success && lastChar != 0) { + if (i == 0) { + firstDecoded = decoded; + } + if (lastChar == cpinfo.UnicodeDefaultChar) { + restoreDecoded = true; + rawparts[id - 1] = *(raw.end() - 1) + rawparts[id - 1]; + raw.resize(raw.size() - 1); + } else { + restoreDecoded = false; + break; + } + } else { + break; + } + } + if (restoreDecoded) { + decoded = firstDecoded; + rawparts[id - 1].clear(); + } + } + } else { + success = DoDecodeText(raw, decoded, NULL); + } + } +#else + static_cast<void>(id); +#endif + return success; +} + +bool cmProcessOutput::DecodeText(const char* data, size_t length, + std::string& decoded, size_t id) +{ + return DecodeText(std::string(data, length), decoded, id); +} + +bool cmProcessOutput::DecodeText(std::vector<char> raw, + std::vector<char>& decoded, size_t id) +{ + std::string str; + const bool success = + DecodeText(std::string(raw.begin(), raw.end()), str, id); + decoded.assign(str.begin(), str.end()); + return success; +} + +#if defined(_WIN32) +bool cmProcessOutput::DoDecodeText(std::string raw, std::string& decoded, + wchar_t* lastChar) +{ + bool success = false; + const int wlength = + MultiByteToWideChar(codepage, 0, raw.c_str(), int(raw.size()), NULL, 0); + wchar_t* wdata = new wchar_t[wlength]; + int r = MultiByteToWideChar(codepage, 0, raw.c_str(), int(raw.size()), wdata, + wlength); + if (r > 0) { + if (lastChar) { + *lastChar = 0; + if ((wlength >= 2 && wdata[wlength - 2] != wdata[wlength - 1]) || + wlength >= 1) { + *lastChar = wdata[wlength - 1]; + } + } + int length = WideCharToMultiByte(defaultCodepage, 0, wdata, wlength, NULL, + 0, NULL, NULL); + char* data = new char[length]; + r = WideCharToMultiByte(defaultCodepage, 0, wdata, wlength, data, length, + NULL, NULL); + if (r > 0) { + decoded = std::string(data, length); + success = true; + } + delete[] data; + } + delete[] wdata; + return success; +} +#endif diff --git a/Source/cmProcessOutput.h b/Source/cmProcessOutput.h new file mode 100644 index 0000000..d7a5e98 --- /dev/null +++ b/Source/cmProcessOutput.h @@ -0,0 +1,80 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmProcessOutput_h +#define cmProcessOutput_h + +#include <cmConfigure.h> // IWYU pragma: keep + +#include <string> +#include <vector> + +/** \class cmProcessOutput + * \brief Decode text data to internal encoding. + * + * cmProcessOutput is used to decode text output from external process + * using external encoding to our internal encoding. + */ +class cmProcessOutput +{ +public: + enum Encoding + { + None, + Auto, + UTF8, + ANSI, + OEM + }; + + /// The code page that is used as internal encoding to which we will encode. + static unsigned int defaultCodepage; + + /** + * A class constructor. + * \param encoding external process encoding from which we will decode. + * \param maxSize a maximal size for process output buffer. It should match + * to KWSYSPE_PIPE_BUFFER_SIZE. If text we decode is same size as \a maxSize + * then we will check for incomplete character at end of buffer and + * we will not return last incomplete character. This character will be + * returned with next DecodeText() call. To disable this behavior specify + * 0 as \a maxSize. + */ + cmProcessOutput(Encoding encoding = Auto, unsigned int maxSize = 1024); + ~cmProcessOutput(); + /** + * Decode \a raw string using external encoding to internal + * encoding in \a decoded. + * \a id specifies which internal buffer to use. This is important when we + * are decoding both stdout and stderr from process output and we need to + * keep incomplete characters in separate buffers for each stream. + * \return true if successfully decoded \a raw to \a decoded or false if not. + */ + bool DecodeText(std::string raw, std::string& decoded, size_t id = 0); + /** + * Decode \a data with \a length from external encoding to internal + * encoding in \a decoded. + * \param data a pointer to process output text data. + * \param length a size of data buffer. + * \param decoded a string which will contain decoded text. + * \param id an internal buffer id to use. + * \return true if successfully decoded \a data to \a decoded or false if + * not. + */ + bool DecodeText(const char* data, size_t length, std::string& decoded, + size_t id = 0); + /** + * \overload + */ + bool DecodeText(std::vector<char> raw, std::vector<char>& decoded, + size_t id = 0); + +private: +#if defined(_WIN32) + unsigned int codepage; + unsigned int bufferSize; + std::vector<std::string> rawparts; + bool DoDecodeText(std::string raw, std::string& decoded, wchar_t* lastChar); +#endif +}; + +#endif diff --git a/Source/cmProcessTools.cxx b/Source/cmProcessTools.cxx index e7b6051..b756650 100644 --- a/Source/cmProcessTools.cxx +++ b/Source/cmProcessTools.cxx @@ -1,29 +1,46 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmProcessTools.h" +#include "cmProcessOutput.h" #include <cmsys/Process.h> #include <ostream> void cmProcessTools::RunProcess(struct cmsysProcess_s* cp, OutputParser* out, - OutputParser* err) + OutputParser* err, Encoding encoding) { cmsysProcess_Execute(cp); char* data = CM_NULLPTR; int length = 0; int p; + cmProcessOutput processOutput(encoding); + std::string strdata; while ((out || err) && (p = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR), p)) { if (out && p == cmsysProcess_Pipe_STDOUT) { - if (!out->Process(data, length)) { + processOutput.DecodeText(data, length, strdata, 1); + if (!out->Process(strdata.c_str(), int(strdata.size()))) { out = CM_NULLPTR; } } else if (err && p == cmsysProcess_Pipe_STDERR) { - if (!err->Process(data, length)) { + processOutput.DecodeText(data, length, strdata, 2); + if (!err->Process(strdata.c_str(), int(strdata.size()))) { err = CM_NULLPTR; } } } + if (out) { + processOutput.DecodeText(std::string(), strdata, 1); + if (!strdata.empty()) { + out->Process(strdata.c_str(), int(strdata.size())); + } + } + if (err) { + processOutput.DecodeText(std::string(), strdata, 2); + if (!strdata.empty()) { + out->Process(strdata.c_str(), int(strdata.size())); + } + } cmsysProcess_WaitForExit(cp, CM_NULLPTR); } diff --git a/Source/cmProcessTools.h b/Source/cmProcessTools.h index e5a3fe9..df131b9 100644 --- a/Source/cmProcessTools.h +++ b/Source/cmProcessTools.h @@ -3,6 +3,7 @@ #ifndef cmProcessTools_h #define cmProcessTools_h +#include "cmProcessOutput.h" #include <cmConfigure.h> #include <iosfwd> @@ -16,6 +17,7 @@ class cmProcessTools { public: + typedef cmProcessOutput::Encoding Encoding; /** Abstract interface for process output parsers. */ class OutputParser { @@ -79,7 +81,8 @@ public: /** Run a process and send output to given parsers. */ static void RunProcess(struct cmsysProcess_s* cp, OutputParser* out, - OutputParser* err = CM_NULLPTR); + OutputParser* err = CM_NULLPTR, + Encoding encoding = cmProcessOutput::Auto); }; #endif diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index 609ad2b..9a06f05 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -386,25 +386,9 @@ bool cmServerProtocol1_0::DoActivate(const cmServerRequest& request, return false; } - const std::string fullGeneratorName = - cmExternalMakefileProjectGenerator::CreateFullGeneratorName( - generator, extraGenerator); - - cm->SetGeneratorToolset(toolset); - cm->SetGeneratorPlatform(platform); - - cmGlobalGenerator* gg = cm->CreateGlobalGenerator(fullGeneratorName); - if (!gg) { - setErrorMessage( - errorMessage, - std::string("Could not set up the requested combination of \"") + - kGENERATOR_KEY + "\" and \"" + kEXTRA_GENERATOR_KEY + "\""); - return false; - } - - cm->SetGlobalGenerator(gg); - cm->SetHomeDirectory(sourceDirectory); - cm->SetHomeOutputDirectory(buildDirectory); + this->GeneratorInfo = + GeneratorInformation(generator, extraGenerator, toolset, platform, + sourceDirectory, buildDirectory); this->m_State = STATE_ACTIVE; return true; @@ -944,6 +928,13 @@ cmServerResponse cmServerProtocol1_0::ProcessConfigure( FileMonitor()->StopMonitoring(); + std::string errorMessage; + cmake* cm = this->CMakeInstance(); + this->GeneratorInfo.SetupGenerator(cm, &errorMessage); + if (!errorMessage.empty()) { + return request.ReportError(errorMessage); + } + // Make sure the types of cacheArguments matches (if given): std::vector<std::string> cacheArgs; bool cacheArgumentsError = false; @@ -968,15 +959,13 @@ cmServerResponse cmServerProtocol1_0::ProcessConfigure( "cacheArguments must be unset, a string or an array of strings."); } - cmake* cm = this->CMakeInstance(); std::string sourceDir = cm->GetHomeDirectory(); const std::string buildDir = cm->GetHomeOutputDirectory(); cmGlobalGenerator* gg = cm->GetGlobalGenerator(); if (buildDir.empty()) { - return request.ReportError( - "No build directory set via setGlobalSettings."); + return request.ReportError("No build directory set via Handshake."); } if (cm->LoadCache(buildDir)) { @@ -1051,14 +1040,12 @@ cmServerResponse cmServerProtocol1_0::ProcessGlobalSettings( obj[kWARN_UNUSED_CLI_KEY] = cm->GetWarnUnusedCli(); obj[kCHECK_SYSTEM_VARS_KEY] = cm->GetCheckSystemVars(); - obj[kSOURCE_DIRECTORY_KEY] = cm->GetHomeDirectory(); - obj[kBUILD_DIRECTORY_KEY] = cm->GetHomeOutputDirectory(); + obj[kSOURCE_DIRECTORY_KEY] = this->GeneratorInfo.SourceDirectory; + obj[kBUILD_DIRECTORY_KEY] = this->GeneratorInfo.BuildDirectory; // Currently used generator: - cmGlobalGenerator* gen = cm->GetGlobalGenerator(); - obj[kGENERATOR_KEY] = gen ? gen->GetName() : std::string(); - obj[kEXTRA_GENERATOR_KEY] = - gen ? gen->GetExtraGeneratorName() : std::string(); + obj[kGENERATOR_KEY] = this->GeneratorInfo.GeneratorName; + obj[kEXTRA_GENERATOR_KEY] = this->GeneratorInfo.ExtraGeneratorName; return request.Reply(obj); } @@ -1122,3 +1109,41 @@ cmServerResponse cmServerProtocol1_0::ProcessFileSystemWatchers( return request.Reply(result); } + +cmServerProtocol1_0::GeneratorInformation::GeneratorInformation( + const std::string& generatorName, const std::string& extraGeneratorName, + const std::string& toolset, const std::string& platform, + const std::string& sourceDirectory, const std::string& buildDirectory) + : GeneratorName(generatorName) + , ExtraGeneratorName(extraGeneratorName) + , Toolset(toolset) + , Platform(platform) + , SourceDirectory(sourceDirectory) + , BuildDirectory(buildDirectory) +{ +} + +void cmServerProtocol1_0::GeneratorInformation::SetupGenerator( + cmake* cm, std::string* errorMessage) +{ + const std::string fullGeneratorName = + cmExternalMakefileProjectGenerator::CreateFullGeneratorName( + GeneratorName, ExtraGeneratorName); + + cm->SetHomeDirectory(SourceDirectory); + cm->SetHomeOutputDirectory(BuildDirectory); + + cmGlobalGenerator* gg = cm->CreateGlobalGenerator(fullGeneratorName); + if (!gg) { + setErrorMessage( + errorMessage, + std::string("Could not set up the requested combination of \"") + + kGENERATOR_KEY + "\" and \"" + kEXTRA_GENERATOR_KEY + "\""); + return; + } + + cm->SetGlobalGenerator(gg); + + cm->SetGeneratorToolset(Toolset); + cm->SetGeneratorPlatform(Platform); +} diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h index 5238d5d..027f145 100644 --- a/Source/cmServerProtocol.h +++ b/Source/cmServerProtocol.h @@ -131,4 +131,28 @@ private: State m_State = STATE_INACTIVE; bool m_isDirty = false; + + struct GeneratorInformation + { + public: + GeneratorInformation() = default; + GeneratorInformation(const std::string& generatorName, + const std::string& extraGeneratorName, + const std::string& toolset, + const std::string& platform, + const std::string& sourceDirectory, + const std::string& buildDirectory); + + void SetupGenerator(cmake* cm, std::string* errorMessage); + + std::string GeneratorName; + std::string ExtraGeneratorName; + std::string Toolset; + std::string Platform; + + std::string SourceDirectory; + std::string BuildDirectory; + }; + + GeneratorInformation GeneratorInfo; }; diff --git a/Source/cmStringCommand.cxx b/Source/cmStringCommand.cxx index f835445..603c990 100644 --- a/Source/cmStringCommand.cxx +++ b/Source/cmStringCommand.cxx @@ -36,7 +36,9 @@ bool cmStringCommand::InitialPass(std::vector<std::string> const& args, } if (subCommand == "MD5" || subCommand == "SHA1" || subCommand == "SHA224" || subCommand == "SHA256" || subCommand == "SHA384" || - subCommand == "SHA512") { + subCommand == "SHA512" || subCommand == "SHA3_224" || + subCommand == "SHA3_256" || subCommand == "SHA3_384" || + subCommand == "SHA3_512") { return this->HandleHashCommand(args); } if (subCommand == "TOLOWER") { diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 7738ab6..029594f 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -3,6 +3,7 @@ #include "cmSystemTools.h" #include "cmAlgorithms.h" +#include "cmProcessOutput.h" #if defined(CMAKE_BUILD_WITH_CMAKE) #include "cmArchiveWrite.h" @@ -573,7 +574,7 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command, std::string* captureStdOut, std::string* captureStdErr, int* retVal, const char* dir, OutputOption outputflag, - double timeout) + double timeout, Encoding encoding) { std::vector<const char*> argv; for (std::vector<std::string>::const_iterator a = command.begin(); @@ -609,6 +610,8 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command, char* data; int length; int pipe; + cmProcessOutput processOutput(encoding); + std::string strdata; if (outputflag != OUTPUT_PASSTHROUGH && (captureStdOut || captureStdErr || outputflag != OUTPUT_NONE)) { while ((pipe = cmsysProcess_WaitForData(cp, &data, &length, CM_NULLPTR)) > @@ -624,28 +627,44 @@ bool cmSystemTools::RunSingleCommand(std::vector<std::string> const& command, if (pipe == cmsysProcess_Pipe_STDOUT) { if (outputflag != OUTPUT_NONE) { - cmSystemTools::Stdout(data, length); + processOutput.DecodeText(data, length, strdata, 1); + cmSystemTools::Stdout(strdata.c_str(), strdata.size()); } if (captureStdOut) { tempStdOut.insert(tempStdOut.end(), data, data + length); } } else if (pipe == cmsysProcess_Pipe_STDERR) { if (outputflag != OUTPUT_NONE) { - cmSystemTools::Stderr(data, length); + processOutput.DecodeText(data, length, strdata, 2); + cmSystemTools::Stderr(strdata.c_str(), strdata.size()); } if (captureStdErr) { tempStdErr.insert(tempStdErr.end(), data, data + length); } } } + + if (outputflag != OUTPUT_NONE) { + processOutput.DecodeText(std::string(), strdata, 1); + if (!strdata.empty()) { + cmSystemTools::Stdout(strdata.c_str(), strdata.size()); + } + processOutput.DecodeText(std::string(), strdata, 2); + if (!strdata.empty()) { + cmSystemTools::Stderr(strdata.c_str(), strdata.size()); + } + } } cmsysProcess_WaitForExit(cp, CM_NULLPTR); + if (captureStdOut) { captureStdOut->assign(tempStdOut.begin(), tempStdOut.end()); + processOutput.DecodeText(*captureStdOut, *captureStdOut); } if (captureStdErr) { captureStdErr->assign(tempStdErr.begin(), tempStdErr.end()); + processOutput.DecodeText(*captureStdErr, *captureStdErr); } bool result = true; @@ -1643,6 +1662,8 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line, line = ""; std::vector<char>::iterator outiter = out.begin(); std::vector<char>::iterator erriter = err.begin(); + cmProcessOutput processOutput; + std::string strdata; while (1) { // Check for a newline in stdout. for (; outiter != out.end(); ++outiter) { @@ -1687,17 +1708,31 @@ int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line, return pipe; } if (pipe == cmsysProcess_Pipe_STDOUT) { + processOutput.DecodeText(data, length, strdata, 1); // Append to the stdout buffer. std::vector<char>::size_type size = out.size(); - out.insert(out.end(), data, data + length); + out.insert(out.end(), strdata.begin(), strdata.end()); outiter = out.begin() + size; } else if (pipe == cmsysProcess_Pipe_STDERR) { + processOutput.DecodeText(data, length, strdata, 2); // Append to the stderr buffer. std::vector<char>::size_type size = err.size(); - err.insert(err.end(), data, data + length); + err.insert(err.end(), strdata.begin(), strdata.end()); erriter = err.begin() + size; } else if (pipe == cmsysProcess_Pipe_None) { // Both stdout and stderr pipes have broken. Return leftover data. + processOutput.DecodeText(std::string(), strdata, 1); + if (!strdata.empty()) { + std::vector<char>::size_type size = out.size(); + out.insert(out.end(), strdata.begin(), strdata.end()); + outiter = out.begin() + size; + } + processOutput.DecodeText(std::string(), strdata, 2); + if (!strdata.empty()) { + std::vector<char>::size_type size = err.size(); + err.insert(err.end(), strdata.begin(), strdata.end()); + erriter = err.begin() + size; + } if (!out.empty()) { line.append(&out[0], outiter - out.begin()); out.erase(out.begin(), out.end()); diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h index 0801f26..10e8280 100644 --- a/Source/cmSystemTools.h +++ b/Source/cmSystemTools.h @@ -5,6 +5,7 @@ #include <cmConfigure.h> // IWYU pragma: keep +#include <cmProcessOutput.h> #include <cmsys/Process.h> #include <cmsys/SystemTools.hxx> #include <stddef.h> @@ -29,6 +30,7 @@ class cmSystemTools : public cmsys::SystemTools { public: typedef cmsys::SystemTools Superclass; + typedef cmProcessOutput::Encoding Encoding; /** Expand out any arguments in the vector that have ; separated * strings into multiple arguments. A new vector is created @@ -239,7 +241,8 @@ public: int* retVal = CM_NULLPTR, const char* dir = CM_NULLPTR, OutputOption outputflag = OUTPUT_MERGE, - double timeout = 0.0); + double timeout = 0.0, + Encoding encoding = cmProcessOutput::Auto); static std::string PrintSingleCommand(std::vector<std::string> const&); diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 5dd9e48..4dabd51 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -314,6 +314,16 @@ void cmVisualStudio10TargetGenerator::Generate() << "</TargetFrameworkVersion>\n"; } + // Disable the project upgrade prompt that is displayed the first time a + // project using an older toolset version is opened in a newer version of + // the IDE (respected by VS 2013 and above). + if (this->GlobalGenerator->GetVersion() >= + cmGlobalVisualStudioGenerator::VS12) { + this->WriteString("<VCProjectUpgraderObjectName>NoUpgrade" + "</VCProjectUpgraderObjectName>\n", + 2); + } + std::vector<std::string> keys = this->GeneratorTarget->GetPropertyKeys(); for (std::vector<std::string>::const_iterator keyIt = keys.begin(); keyIt != keys.end(); ++keyIt) { diff --git a/Tests/CMakeTests/File-SHA3_224-Works.cmake b/Tests/CMakeTests/File-SHA3_224-Works.cmake new file mode 100644 index 0000000..e4f4e85 --- /dev/null +++ b/Tests/CMakeTests/File-SHA3_224-Works.cmake @@ -0,0 +1,2 @@ +file(SHA3_224 ${CMAKE_CURRENT_LIST_DIR}/File-HASH-Input.txt sha3_224) +message("${sha3_224}") diff --git a/Tests/CMakeTests/File-SHA3_256-Works.cmake b/Tests/CMakeTests/File-SHA3_256-Works.cmake new file mode 100644 index 0000000..189c8a2 --- /dev/null +++ b/Tests/CMakeTests/File-SHA3_256-Works.cmake @@ -0,0 +1,2 @@ +file(SHA3_256 ${CMAKE_CURRENT_LIST_DIR}/File-HASH-Input.txt sha3_256) +message("${sha3_256}") diff --git a/Tests/CMakeTests/File-SHA3_384-Works.cmake b/Tests/CMakeTests/File-SHA3_384-Works.cmake new file mode 100644 index 0000000..08f9f5b --- /dev/null +++ b/Tests/CMakeTests/File-SHA3_384-Works.cmake @@ -0,0 +1,2 @@ +file(SHA3_384 ${CMAKE_CURRENT_LIST_DIR}/File-HASH-Input.txt sha3_384) +message("${sha3_384}") diff --git a/Tests/CMakeTests/File-SHA3_512-Works.cmake b/Tests/CMakeTests/File-SHA3_512-Works.cmake new file mode 100644 index 0000000..4182196 --- /dev/null +++ b/Tests/CMakeTests/File-SHA3_512-Works.cmake @@ -0,0 +1,2 @@ +file(SHA3_512 ${CMAKE_CURRENT_LIST_DIR}/File-HASH-Input.txt sha3_512) +message("${sha3_512}") diff --git a/Tests/CMakeTests/FileTest.cmake.in b/Tests/CMakeTests/FileTest.cmake.in index 61523e6..71cb3db 100644 --- a/Tests/CMakeTests/FileTest.cmake.in +++ b/Tests/CMakeTests/FileTest.cmake.in @@ -36,6 +36,14 @@ set(SHA384-Works-RESULT 0) set(SHA384-Works-STDERR "1de9560b4e030e02051ea408200ffc55d70c97ac64ebf822461a5c786f495c36df43259b14483bc8d364f0106f4971ee") set(SHA512-Works-RESULT 0) set(SHA512-Works-STDERR "3982a1b4e651768bec70ab1fb97045cb7a659f4ba7203d501c52ab2e803071f9d5fd272022df15f27727fc67f8cd022e710e29010b2a9c0b467c111e2f6abf51") +set(SHA3_224-Works-RESULT 0) +set(SHA3_224-Works-STDERR "4272868085f4f25080681a7712509fd12e16dcda79bd356836dd2100") +set(SHA3_256-Works-RESULT 0) +set(SHA3_256-Works-STDERR "be0df472b6bd474417a166d12f2774f2ef5095e86f0a88ef4c78c703800cfc8a") +set(SHA3_384-Works-RESULT 0) +set(SHA3_384-Works-STDERR "935a17cc708443c1369549483656a4521af03a52e4f3b314566272017ccae03a2c5db838f6d4c156b1dc5c366182481b") +set(SHA3_512-Works-RESULT 0) +set(SHA3_512-Works-STDERR "471a85ed537e8f77f31412a089f22d836054ffa179599f87a5d7568927d8fa236b6793ded8a387d1de92398c967177bcc6361672a722bf736cb0f63a0956d5cf") set(TIMESTAMP-NoFile-RESULT 0) set(TIMESTAMP-NoFile-STDERR "~~") set(TIMESTAMP-BadArg1-RESULT 1) @@ -66,6 +74,10 @@ check_cmake_test(File SHA256-Works SHA384-Works SHA512-Works + SHA3_224-Works + SHA3_256-Works + SHA3_384-Works + SHA3_512-Works TIMESTAMP-NoFile TIMESTAMP-BadArg1 TIMESTAMP-NotBogus diff --git a/Tests/CMakeTests/String-SHA3_224-Works.cmake b/Tests/CMakeTests/String-SHA3_224-Works.cmake new file mode 100644 index 0000000..6aeb91d --- /dev/null +++ b/Tests/CMakeTests/String-SHA3_224-Works.cmake @@ -0,0 +1,2 @@ +string(SHA3_224 sha3_224 "sample input string\n") +message("${sha3_224}") diff --git a/Tests/CMakeTests/String-SHA3_256-Works.cmake b/Tests/CMakeTests/String-SHA3_256-Works.cmake new file mode 100644 index 0000000..cc7ea1a --- /dev/null +++ b/Tests/CMakeTests/String-SHA3_256-Works.cmake @@ -0,0 +1,2 @@ +string(SHA3_256 sha3_256 "sample input string\n") +message("${sha3_256}") diff --git a/Tests/CMakeTests/String-SHA3_384-Works.cmake b/Tests/CMakeTests/String-SHA3_384-Works.cmake new file mode 100644 index 0000000..9341c3f --- /dev/null +++ b/Tests/CMakeTests/String-SHA3_384-Works.cmake @@ -0,0 +1,2 @@ +string(SHA3_384 sha3_384 "sample input string\n") +message("${sha3_384}") diff --git a/Tests/CMakeTests/String-SHA3_512-Works.cmake b/Tests/CMakeTests/String-SHA3_512-Works.cmake new file mode 100644 index 0000000..cf4eddd --- /dev/null +++ b/Tests/CMakeTests/String-SHA3_512-Works.cmake @@ -0,0 +1,2 @@ +string(SHA3_512 sha3_512 "sample input string\n") +message("${sha3_512}") diff --git a/Tests/CMakeTests/StringTest.cmake.in b/Tests/CMakeTests/StringTest.cmake.in index a45b205..83655da 100644 --- a/Tests/CMakeTests/StringTest.cmake.in +++ b/Tests/CMakeTests/StringTest.cmake.in @@ -16,6 +16,14 @@ set(SHA384-Works-RESULT 0) set(SHA384-Works-STDERR "1de9560b4e030e02051ea408200ffc55d70c97ac64ebf822461a5c786f495c36df43259b14483bc8d364f0106f4971ee") set(SHA512-Works-RESULT 0) set(SHA512-Works-STDERR "3982a1b4e651768bec70ab1fb97045cb7a659f4ba7203d501c52ab2e803071f9d5fd272022df15f27727fc67f8cd022e710e29010b2a9c0b467c111e2f6abf51") +set(SHA3_224-Works-RESULT 0) +set(SHA3_224-Works-STDERR "4272868085f4f25080681a7712509fd12e16dcda79bd356836dd2100") +set(SHA3_256-Works-RESULT 0) +set(SHA3_256-Works-STDERR "be0df472b6bd474417a166d12f2774f2ef5095e86f0a88ef4c78c703800cfc8a") +set(SHA3_384-Works-RESULT 0) +set(SHA3_384-Works-STDERR "935a17cc708443c1369549483656a4521af03a52e4f3b314566272017ccae03a2c5db838f6d4c156b1dc5c366182481b") +set(SHA3_512-Works-RESULT 0) +set(SHA3_512-Works-STDERR "471a85ed537e8f77f31412a089f22d836054ffa179599f87a5d7568927d8fa236b6793ded8a387d1de92398c967177bcc6361672a722bf736cb0f63a0956d5cf") set(TIMESTAMP-BadArg1-RESULT 1) set(TIMESTAMP-BadArg1-STDERR "string sub-command TIMESTAMP requires at least one argument") set(TIMESTAMP-BadArg2-RESULT 1) @@ -52,6 +60,10 @@ check_cmake_test(String SHA256-Works SHA384-Works SHA512-Works + SHA3_224-Works + SHA3_256-Works + SHA3_384-Works + SHA3_512-Works TIMESTAMP-BadArg1 TIMESTAMP-BadArg2 TIMESTAMP-BadArg3 diff --git a/Tests/ExternalProjectLocal/CMakeLists.txt b/Tests/ExternalProjectLocal/CMakeLists.txt index 17f1630..5b94163 100644 --- a/Tests/ExternalProjectLocal/CMakeLists.txt +++ b/Tests/ExternalProjectLocal/CMakeLists.txt @@ -131,6 +131,7 @@ ExternalProject_Add(${proj} CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -G ${CMAKE_GENERATOR} <SOURCE_DIR> INSTALL_COMMAND "" LOG_BUILD 1 + UPDATE_DISCONNECTED 1 ) set_property(TARGET ${proj} PROPERTY FOLDER "Local/TGZ") diff --git a/Tests/Module/ExternalData/SHA3_256/.gitattributes b/Tests/Module/ExternalData/SHA3_256/.gitattributes new file mode 100644 index 0000000..3e51d39 --- /dev/null +++ b/Tests/Module/ExternalData/SHA3_256/.gitattributes @@ -0,0 +1 @@ +* -crlf diff --git a/Tests/Module/ExternalData/SHA3_256/c01b0bfd51ece4295c7b45493750a3612ecc483095eb1366f9f46b179550e231 b/Tests/Module/ExternalData/SHA3_256/c01b0bfd51ece4295c7b45493750a3612ecc483095eb1366f9f46b179550e231 new file mode 100644 index 0000000..0377f5d --- /dev/null +++ b/Tests/Module/ExternalData/SHA3_256/c01b0bfd51ece4295c7b45493750a3612ecc483095eb1366f9f46b179550e231 @@ -0,0 +1 @@ +SeriesMixed.5 diff --git a/Tests/Module/ExternalData/SeriesMixed.5.dat.sha3-256 b/Tests/Module/ExternalData/SeriesMixed.5.dat.sha3-256 new file mode 100644 index 0000000..1a5db39 --- /dev/null +++ b/Tests/Module/ExternalData/SeriesMixed.5.dat.sha3-256 @@ -0,0 +1 @@ +c01b0bfd51ece4295c7b45493750a3612ecc483095eb1366f9f46b179550e231 diff --git a/Tests/RunCMake/CPack/RunCMakeTest.cmake b/Tests/RunCMake/CPack/RunCMakeTest.cmake index 38bd0ea..61d4332 100644 --- a/Tests/RunCMake/CPack/RunCMakeTest.cmake +++ b/Tests/RunCMake/CPack/RunCMakeTest.cmake @@ -22,4 +22,4 @@ run_cpack_test(DEB_GENERATE_SHLIBS_LDCONFIG "DEB" true) run_cpack_test(DEBUGINFO "RPM" true) run_cpack_test_subtests(SINGLE_DEBUGINFO "no_main_component;one_component;one_component_main;no_debuginfo;one_component_no_debuginfo;no_components;valid" "RPM" true) run_cpack_test(LONG_FILENAMES "DEB" false) -run_cpack_test_subtests(PACKAGE_CHECKSUM "invalid;MD5;SHA1;SHA224;SHA256;SHA384;SHA512" "TGZ" false) +run_cpack_test_subtests(PACKAGE_CHECKSUM "invalid;MD5;SHA1;SHA224;SHA256;SHA384;SHA512;SHA3_224;SHA3_256;SHA3_384;SHA3_512" "TGZ" false) diff --git a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake index cc2cc2e..22d8164 100644 --- a/Tests/RunCMake/VS10Project/RunCMakeTest.cmake +++ b/Tests/RunCMake/VS10Project/RunCMakeTest.cmake @@ -1,2 +1,3 @@ include(RunCMake) run_cmake(VsConfigurationType) +run_cmake(VsTargetsFileReferences) diff --git a/Tests/RunCMake/VS10Project/VsTargetsFileReferences-check.cmake b/Tests/RunCMake/VS10Project/VsTargetsFileReferences-check.cmake new file mode 100644 index 0000000..3d01c2c --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsTargetsFileReferences-check.cmake @@ -0,0 +1,45 @@ +set(files foo.vcxproj bar.vcxproj baz.vcxproj) + +foreach(file ${files}) + set(vsProjectFile ${RunCMake_TEST_BINARY_DIR}/${file}) + + if(NOT EXISTS "${vsProjectFile}") + set(RunCMake_TEST_FAILED "Project file ${vsProjectFile} does not exist.") + return() + endif() + + set(waldoFound FALSE) + set(xyzzyFound FALSE) + file(STRINGS "${vsProjectFile}" lines) + foreach(line IN LISTS lines) + if(line MATCHES "^ *<Import Project=.*/>$") + if(line MATCHES "^.*waldo.targets.*$") + set(waldoFound TRUE) + message(STATUS "${file} is importing waldo.targets") + elseif(line MATCHES "^.*xyzzy.targets.*$") + set(xyzzyFound TRUE) + message(STATUS "${file} is importing xyzzy.targets") + endif() + endif() + endforeach() + + if("${file}" STREQUAL "foo.vcxproj") + if(NOT xyzzyFound) + set(RunCMake_TEST_FAILED "xyzzy.targets not imported from ${file}") + return() + endif() + if(waldoFound) + set(RunCMake_TEST_FAILED "waldo.targets imported from ${file}") + return() + endif() + else() + if(NOT xyzzyFound) + set(RunCMake_TEST_FAILED "xyzzy.targets not imported from ${file}") + return() + endif() + if(NOT waldoFound) + set(RunCMake_TEST_FAILED "waldo.targets not imported from ${file}") + return() + endif() + endif() +endforeach() diff --git a/Tests/RunCMake/VS10Project/VsTargetsFileReferences.cmake b/Tests/RunCMake/VS10Project/VsTargetsFileReferences.cmake new file mode 100644 index 0000000..5ca4f1f --- /dev/null +++ b/Tests/RunCMake/VS10Project/VsTargetsFileReferences.cmake @@ -0,0 +1,9 @@ +enable_language(CXX) +add_library(foo foo.cpp) +target_link_libraries(foo ${CMAKE_BINARY_DIR}/xyzzy.targets) + +add_library(bar bar.cpp) +target_link_libraries(bar foo ${CMAKE_BINARY_DIR}/waldo.targets) + +add_executable(baz baz.cpp) +target_link_libraries(baz bar) diff --git a/Tests/RunCMake/VS10Project/bar.cpp b/Tests/RunCMake/VS10Project/bar.cpp new file mode 100644 index 0000000..b72a1a5 --- /dev/null +++ b/Tests/RunCMake/VS10Project/bar.cpp @@ -0,0 +1,3 @@ +void bar() +{ +} diff --git a/Tests/RunCMake/VS10Project/baz.cpp b/Tests/RunCMake/VS10Project/baz.cpp new file mode 100644 index 0000000..d5d334a --- /dev/null +++ b/Tests/RunCMake/VS10Project/baz.cpp @@ -0,0 +1,3 @@ +void baz() +{ +} diff --git a/Utilities/Scripts/update-librhash.bash b/Utilities/Scripts/update-librhash.bash index 2f67ea2..009ce32 100755 --- a/Utilities/Scripts/update-librhash.bash +++ b/Utilities/Scripts/update-librhash.bash @@ -27,6 +27,8 @@ readonly paths=" librhash/sha1.h librhash/sha256.c librhash/sha256.h + librhash/sha3.c + librhash/sha3.h librhash/sha512.c librhash/sha512.h librhash/ustd.h diff --git a/Utilities/cmlibrhash/CMakeLists.txt b/Utilities/cmlibrhash/CMakeLists.txt index 340d946..aa28055 100644 --- a/Utilities/cmlibrhash/CMakeLists.txt +++ b/Utilities/cmlibrhash/CMakeLists.txt @@ -23,6 +23,8 @@ set(librhash_sources librhash/sha1.h librhash/sha256.c librhash/sha256.h + librhash/sha3.c + librhash/sha3.h librhash/sha512.c librhash/sha512.h librhash/ustd.h diff --git a/Utilities/cmlibrhash/librhash/algorithms.c b/Utilities/cmlibrhash/librhash/algorithms.c index 56d20b8..fc01690 100644 --- a/Utilities/cmlibrhash/librhash/algorithms.c +++ b/Utilities/cmlibrhash/librhash/algorithms.c @@ -39,8 +39,8 @@ #include "sha1.h" #include "sha256.h" #include "sha512.h" -#if 0 #include "sha3.h" +#if 0 #include "tiger.h" #include "tth.h" #include "whirlpool.h" @@ -104,11 +104,11 @@ rhash_info info_sha512 = { RHASH_SHA512, F_BE64, 64, "SHA-512", "sha512" }; #if 0 rhash_info info_edr256 = { RHASH_EDONR256, F_LE32, 32, "EDON-R256", "edon-r256" }; rhash_info info_edr512 = { RHASH_EDONR512, F_LE64, 64, "EDON-R512", "edon-r512" }; +#endif rhash_info info_sha3_224 = { RHASH_SHA3_224, F_LE64, 28, "SHA3-224", "sha3-224" }; rhash_info info_sha3_256 = { RHASH_SHA3_256, F_LE64, 32, "SHA3-256", "sha3-256" }; rhash_info info_sha3_384 = { RHASH_SHA3_384, F_LE64, 48, "SHA3-384", "sha3-384" }; rhash_info info_sha3_512 = { RHASH_SHA3_512, F_LE64, 64, "SHA3-512", "sha3-512" }; -#endif /* some helper macros */ #define dgshft(name) (((char*)&((name##_ctx*)0)->hash) - (char*)0) @@ -148,11 +148,11 @@ rhash_hash_info rhash_hash_info_default[RHASH_HASH_COUNT] = #if 0 { &info_edr256, sizeof(edonr_ctx), dgshft2(edonr, u.data256.hash) + 32, iuf(rhash_edonr256), 0 }, /* 256 bit */ { &info_edr512, sizeof(edonr_ctx), dgshft2(edonr, u.data512.hash) + 64, iuf(rhash_edonr512), 0 }, /* 512 bit */ +#endif { &info_sha3_224, sizeof(sha3_ctx), dgshft(sha3), ini(rhash_sha3_224), upd(rhash_sha3), fin(rhash_sha3), 0 }, /* 224 bit */ { &info_sha3_256, sizeof(sha3_ctx), dgshft(sha3), ini(rhash_sha3_256), upd(rhash_sha3), fin(rhash_sha3), 0 }, /* 256 bit */ { &info_sha3_384, sizeof(sha3_ctx), dgshft(sha3), ini(rhash_sha3_384), upd(rhash_sha3), fin(rhash_sha3), 0 }, /* 384 bit */ { &info_sha3_512, sizeof(sha3_ctx), dgshft(sha3), ini(rhash_sha3_512), upd(rhash_sha3), fin(rhash_sha3), 0 }, /* 512 bit */ -#endif }; /** diff --git a/Utilities/cmlibrhash/librhash/rhash.h b/Utilities/cmlibrhash/librhash/rhash.h index 6d18c18..cee0e25 100644 --- a/Utilities/cmlibrhash/librhash/rhash.h +++ b/Utilities/cmlibrhash/librhash/rhash.h @@ -66,14 +66,22 @@ enum rhash_ids RHASH_SHA256 = 0x08, RHASH_SHA384 = 0x10, RHASH_SHA512 = 0x20, + RHASH_SHA3_224 = 0x40, + RHASH_SHA3_256 = 0x80, + RHASH_SHA3_384 = 0x100, + RHASH_SHA3_512 = 0x200, RHASH_ALL_HASHES = RHASH_MD5 | RHASH_SHA1 | RHASH_SHA224 | RHASH_SHA256 | RHASH_SHA384 | - RHASH_SHA512, - RHASH_HASH_COUNT = 6 + RHASH_SHA512 | + RHASH_SHA3_224 | + RHASH_SHA3_256 | + RHASH_SHA3_384 | + RHASH_SHA3_512, + RHASH_HASH_COUNT = 10 #endif }; @@ -145,7 +153,7 @@ typedef struct rhash_info /* information functions */ RHASH_API int rhash_count(void); /* number of supported hashes */ RHASH_API int rhash_get_digest_size(unsigned hash_id); /* size of binary message digest */ -RHASH_API int rhash_get_hash_length(unsigned hash_id); /* length of formated hash string */ +RHASH_API int rhash_get_hash_length(unsigned hash_id); /* length of formatted hash string */ RHASH_API int rhash_is_base32(unsigned hash_id); /* default digest output format */ RHASH_API const char* rhash_get_name(unsigned hash_id); /* get hash function name */ RHASH_API const char* rhash_get_magnet_name(unsigned hash_id); /* get name part of magnet urn */ diff --git a/Utilities/cmlibrhash/librhash/sha3.c b/Utilities/cmlibrhash/librhash/sha3.c new file mode 100644 index 0000000..e4a845f --- /dev/null +++ b/Utilities/cmlibrhash/librhash/sha3.c @@ -0,0 +1,356 @@ +/* sha3.c - an implementation of Secure Hash Algorithm 3 (Keccak). + * based on the + * The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011 + * by Guido Bertoni, Joan Daemen, Michaƫl Peeters and Gilles Van Assche + * + * Copyright: 2013 Aleksey Kravchenko <rhash.admin@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk! + */ + +#include <assert.h> +#include <string.h> +#include "byte_order.h" +#include "sha3.h" + +/* constants */ +#define NumberOfRounds 24 + +/* SHA3 (Keccak) constants for 24 rounds */ +static uint64_t keccak_round_constants[NumberOfRounds] = { + I64(0x0000000000000001), I64(0x0000000000008082), I64(0x800000000000808A), I64(0x8000000080008000), + I64(0x000000000000808B), I64(0x0000000080000001), I64(0x8000000080008081), I64(0x8000000000008009), + I64(0x000000000000008A), I64(0x0000000000000088), I64(0x0000000080008009), I64(0x000000008000000A), + I64(0x000000008000808B), I64(0x800000000000008B), I64(0x8000000000008089), I64(0x8000000000008003), + I64(0x8000000000008002), I64(0x8000000000000080), I64(0x000000000000800A), I64(0x800000008000000A), + I64(0x8000000080008081), I64(0x8000000000008080), I64(0x0000000080000001), I64(0x8000000080008008) +}; + +/* Initializing a sha3 context for given number of output bits */ +static void rhash_keccak_init(sha3_ctx *ctx, unsigned bits) +{ + /* NB: The Keccak capacity parameter = bits * 2 */ + unsigned rate = 1600 - bits * 2; + + memset(ctx, 0, sizeof(sha3_ctx)); + ctx->block_size = rate / 8; + assert(rate <= 1600 && (rate % 64) == 0); +} + +/** + * Initialize context before calculating hash. + * + * @param ctx context to initialize + */ +void rhash_sha3_224_init(sha3_ctx *ctx) +{ + rhash_keccak_init(ctx, 224); +} + +/** + * Initialize context before calculating hash. + * + * @param ctx context to initialize + */ +void rhash_sha3_256_init(sha3_ctx *ctx) +{ + rhash_keccak_init(ctx, 256); +} + +/** + * Initialize context before calculating hash. + * + * @param ctx context to initialize + */ +void rhash_sha3_384_init(sha3_ctx *ctx) +{ + rhash_keccak_init(ctx, 384); +} + +/** + * Initialize context before calculating hash. + * + * @param ctx context to initialize + */ +void rhash_sha3_512_init(sha3_ctx *ctx) +{ + rhash_keccak_init(ctx, 512); +} + +/* Keccak theta() transformation */ +static void keccak_theta(uint64_t *A) +{ + unsigned int x; + uint64_t C[5], D[5]; + + for (x = 0; x < 5; x++) { + C[x] = A[x] ^ A[x + 5] ^ A[x + 10] ^ A[x + 15] ^ A[x + 20]; + } + D[0] = ROTL64(C[1], 1) ^ C[4]; + D[1] = ROTL64(C[2], 1) ^ C[0]; + D[2] = ROTL64(C[3], 1) ^ C[1]; + D[3] = ROTL64(C[4], 1) ^ C[2]; + D[4] = ROTL64(C[0], 1) ^ C[3]; + + for (x = 0; x < 5; x++) { + A[x] ^= D[x]; + A[x + 5] ^= D[x]; + A[x + 10] ^= D[x]; + A[x + 15] ^= D[x]; + A[x + 20] ^= D[x]; + } +} + +/* Keccak pi() transformation */ +static void keccak_pi(uint64_t *A) +{ + uint64_t A1; + A1 = A[1]; + A[ 1] = A[ 6]; + A[ 6] = A[ 9]; + A[ 9] = A[22]; + A[22] = A[14]; + A[14] = A[20]; + A[20] = A[ 2]; + A[ 2] = A[12]; + A[12] = A[13]; + A[13] = A[19]; + A[19] = A[23]; + A[23] = A[15]; + A[15] = A[ 4]; + A[ 4] = A[24]; + A[24] = A[21]; + A[21] = A[ 8]; + A[ 8] = A[16]; + A[16] = A[ 5]; + A[ 5] = A[ 3]; + A[ 3] = A[18]; + A[18] = A[17]; + A[17] = A[11]; + A[11] = A[ 7]; + A[ 7] = A[10]; + A[10] = A1; + /* note: A[ 0] is left as is */ +} + +/* Keccak chi() transformation */ +static void keccak_chi(uint64_t *A) +{ + int i; + for (i = 0; i < 25; i += 5) { + uint64_t A0 = A[0 + i], A1 = A[1 + i]; + A[0 + i] ^= ~A1 & A[2 + i]; + A[1 + i] ^= ~A[2 + i] & A[3 + i]; + A[2 + i] ^= ~A[3 + i] & A[4 + i]; + A[3 + i] ^= ~A[4 + i] & A0; + A[4 + i] ^= ~A0 & A1; + } +} + +static void rhash_sha3_permutation(uint64_t *state) +{ + int round; + for (round = 0; round < NumberOfRounds; round++) + { + keccak_theta(state); + + /* apply Keccak rho() transformation */ + state[ 1] = ROTL64(state[ 1], 1); + state[ 2] = ROTL64(state[ 2], 62); + state[ 3] = ROTL64(state[ 3], 28); + state[ 4] = ROTL64(state[ 4], 27); + state[ 5] = ROTL64(state[ 5], 36); + state[ 6] = ROTL64(state[ 6], 44); + state[ 7] = ROTL64(state[ 7], 6); + state[ 8] = ROTL64(state[ 8], 55); + state[ 9] = ROTL64(state[ 9], 20); + state[10] = ROTL64(state[10], 3); + state[11] = ROTL64(state[11], 10); + state[12] = ROTL64(state[12], 43); + state[13] = ROTL64(state[13], 25); + state[14] = ROTL64(state[14], 39); + state[15] = ROTL64(state[15], 41); + state[16] = ROTL64(state[16], 45); + state[17] = ROTL64(state[17], 15); + state[18] = ROTL64(state[18], 21); + state[19] = ROTL64(state[19], 8); + state[20] = ROTL64(state[20], 18); + state[21] = ROTL64(state[21], 2); + state[22] = ROTL64(state[22], 61); + state[23] = ROTL64(state[23], 56); + state[24] = ROTL64(state[24], 14); + + keccak_pi(state); + keccak_chi(state); + + /* apply iota(state, round) */ + *state ^= keccak_round_constants[round]; + } +} + +/** + * The core transformation. Process the specified block of data. + * + * @param hash the algorithm state + * @param block the message block to process + * @param block_size the size of the processed block in bytes + */ +static void rhash_sha3_process_block(uint64_t hash[25], const uint64_t *block, size_t block_size) +{ + /* expanded loop */ + hash[ 0] ^= le2me_64(block[ 0]); + hash[ 1] ^= le2me_64(block[ 1]); + hash[ 2] ^= le2me_64(block[ 2]); + hash[ 3] ^= le2me_64(block[ 3]); + hash[ 4] ^= le2me_64(block[ 4]); + hash[ 5] ^= le2me_64(block[ 5]); + hash[ 6] ^= le2me_64(block[ 6]); + hash[ 7] ^= le2me_64(block[ 7]); + hash[ 8] ^= le2me_64(block[ 8]); + /* if not sha3-512 */ + if (block_size > 72) { + hash[ 9] ^= le2me_64(block[ 9]); + hash[10] ^= le2me_64(block[10]); + hash[11] ^= le2me_64(block[11]); + hash[12] ^= le2me_64(block[12]); + /* if not sha3-384 */ + if (block_size > 104) { + hash[13] ^= le2me_64(block[13]); + hash[14] ^= le2me_64(block[14]); + hash[15] ^= le2me_64(block[15]); + hash[16] ^= le2me_64(block[16]); + /* if not sha3-256 */ + if (block_size > 136) { + hash[17] ^= le2me_64(block[17]); +#ifdef FULL_SHA3_FAMILY_SUPPORT + /* if not sha3-224 */ + if (block_size > 144) { + hash[18] ^= le2me_64(block[18]); + hash[19] ^= le2me_64(block[19]); + hash[20] ^= le2me_64(block[20]); + hash[21] ^= le2me_64(block[21]); + hash[22] ^= le2me_64(block[22]); + hash[23] ^= le2me_64(block[23]); + hash[24] ^= le2me_64(block[24]); + } +#endif + } + } + } + /* make a permutation of the hash */ + rhash_sha3_permutation(hash); +} + +#define SHA3_FINALIZED 0x80000000 + +/** + * Calculate message hash. + * Can be called repeatedly with chunks of the message to be hashed. + * + * @param ctx the algorithm context containing current hashing state + * @param msg message chunk + * @param size length of the message chunk + */ +void rhash_sha3_update(sha3_ctx *ctx, const unsigned char *msg, size_t size) +{ + size_t index = (size_t)ctx->rest; + size_t block_size = (size_t)ctx->block_size; + + if (ctx->rest & SHA3_FINALIZED) return; /* too late for additional input */ + ctx->rest = (unsigned)((ctx->rest + size) % block_size); + + /* fill partial block */ + if (index) { + size_t left = block_size - index; + memcpy((char*)ctx->message + index, msg, (size < left ? size : left)); + if (size < left) return; + + /* process partial block */ + rhash_sha3_process_block(ctx->hash, ctx->message, block_size); + msg += left; + size -= left; + } + while (size >= block_size) { + uint64_t* aligned_message_block; + if (IS_ALIGNED_64(msg)) { + /* the most common case is processing of an already aligned message + without copying it */ + aligned_message_block = (uint64_t*)msg; + } else { + memcpy(ctx->message, msg, block_size); + aligned_message_block = ctx->message; + } + + rhash_sha3_process_block(ctx->hash, aligned_message_block, block_size); + msg += block_size; + size -= block_size; + } + if (size) { + memcpy(ctx->message, msg, size); /* save leftovers */ + } +} + +/** + * Store calculated hash into the given array. + * + * @param ctx the algorithm context containing current hashing state + * @param result calculated hash in binary form + */ +void rhash_sha3_final(sha3_ctx *ctx, unsigned char* result) +{ + size_t digest_length = 100 - ctx->block_size / 2; + const size_t block_size = ctx->block_size; + + if (!(ctx->rest & SHA3_FINALIZED)) + { + /* clear the rest of the data queue */ + memset((char*)ctx->message + ctx->rest, 0, block_size - ctx->rest); + ((char*)ctx->message)[ctx->rest] |= 0x06; + ((char*)ctx->message)[block_size - 1] |= 0x80; + + /* process final block */ + rhash_sha3_process_block(ctx->hash, ctx->message, block_size); + ctx->rest = SHA3_FINALIZED; /* mark context as finalized */ + } + + assert(block_size > digest_length); + if (result) me64_to_le_str(result, ctx->hash, digest_length); +} + +#ifdef USE_KECCAK +/** +* Store calculated hash into the given array. +* +* @param ctx the algorithm context containing current hashing state +* @param result calculated hash in binary form +*/ +void rhash_keccak_final(sha3_ctx *ctx, unsigned char* result) +{ + size_t digest_length = 100 - ctx->block_size / 2; + const size_t block_size = ctx->block_size; + + if (!(ctx->rest & SHA3_FINALIZED)) + { + /* clear the rest of the data queue */ + memset((char*)ctx->message + ctx->rest, 0, block_size - ctx->rest); + ((char*)ctx->message)[ctx->rest] |= 0x01; + ((char*)ctx->message)[block_size - 1] |= 0x80; + + /* process final block */ + rhash_sha3_process_block(ctx->hash, ctx->message, block_size); + ctx->rest = SHA3_FINALIZED; /* mark context as finalized */ + } + + assert(block_size > digest_length); + if (result) me64_to_le_str(result, ctx->hash, digest_length); +} +#endif /* USE_KECCAK */ diff --git a/Utilities/cmlibrhash/librhash/sha3.h b/Utilities/cmlibrhash/librhash/sha3.h new file mode 100644 index 0000000..2831997 --- /dev/null +++ b/Utilities/cmlibrhash/librhash/sha3.h @@ -0,0 +1,54 @@ +/* sha3.h */ +#ifndef RHASH_SHA3_H +#define RHASH_SHA3_H +#include "ustd.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define sha3_224_hash_size 28 +#define sha3_256_hash_size 32 +#define sha3_384_hash_size 48 +#define sha3_512_hash_size 64 +#define sha3_max_permutation_size 25 +#define sha3_max_rate_in_qwords 24 + +/** + * SHA3 Algorithm context. + */ +typedef struct sha3_ctx +{ + /* 1600 bits algorithm hashing state */ + uint64_t hash[sha3_max_permutation_size]; + /* 1536-bit buffer for leftovers */ + uint64_t message[sha3_max_rate_in_qwords]; + /* count of bytes in the message[] buffer */ + unsigned rest; + /* size of a message block processed at once */ + unsigned block_size; +} sha3_ctx; + +/* methods for calculating the hash function */ + +void rhash_sha3_224_init(sha3_ctx *ctx); +void rhash_sha3_256_init(sha3_ctx *ctx); +void rhash_sha3_384_init(sha3_ctx *ctx); +void rhash_sha3_512_init(sha3_ctx *ctx); +void rhash_sha3_update(sha3_ctx *ctx, const unsigned char* msg, size_t size); +void rhash_sha3_final(sha3_ctx *ctx, unsigned char* result); + +#ifdef USE_KECCAK +#define rhash_keccak_224_init rhash_sha3_224_init +#define rhash_keccak_256_init rhash_sha3_256_init +#define rhash_keccak_384_init rhash_sha3_384_init +#define rhash_keccak_512_init rhash_sha3_512_init +#define rhash_keccak_update rhash_sha3_update +void rhash_keccak_final(sha3_ctx *ctx, unsigned char* result); +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* RHASH_SHA3_H */ @@ -372,6 +372,7 @@ CMAKE_CXX_SOURCES="\ cmParseArgumentsCommand \ cmPathLabel \ cmPolicies \ + cmProcessOutput \ cmProjectCommand \ cmProperty \ cmPropertyDefinition \ @@ -1423,6 +1424,7 @@ fi cmake_c_flags_String="-DKWSYS_STRING_C" if ${cmake_system_mingw}; then cmake_c_flags_EncodingC="-DKWSYS_ENCODING_DEFAULT_CODEPAGE=CP_ACP" + cmake_cxx_flags_cmProcessOutput="${cmake_c_flags_EncodingC}" fi cmake_cxx_flags_SystemTools=" -DKWSYS_CXX_HAS_SETENV=${KWSYS_CXX_HAS_SETENV} @@ -1439,8 +1441,9 @@ echo "cmake: ${objs}" > "${cmake_bootstrap_dir}/Makefile" echo " ${cmake_cxx_compiler} ${cmake_ld_flags} ${cmake_cxx_flags} ${objs} -o cmake" >> "${cmake_bootstrap_dir}/Makefile" for a in ${CMAKE_CXX_SOURCES}; do src=`cmake_escape "${cmake_source_dir}/Source/${a}.cxx"` + src_flags=`eval echo \\${cmake_cxx_flags_\${a}}` echo "${a}.o : ${src} ${dep}" >> "${cmake_bootstrap_dir}/Makefile" - echo " ${cmake_cxx_compiler} ${cmake_cxx_flags} -c ${src} -o ${a}.o" >> "${cmake_bootstrap_dir}/Makefile" + echo " ${cmake_cxx_compiler} ${cmake_cxx_flags} ${src_flags} -c ${src} -o ${a}.o" >> "${cmake_bootstrap_dir}/Makefile" done echo "cmBootstrapCommands1.o : $cmBootstrapCommands1Deps" >> "${cmake_bootstrap_dir}/Makefile" echo "cmBootstrapCommands2.o : $cmBootstrapCommands2Deps" >> "${cmake_bootstrap_dir}/Makefile" |