From fb795d02f96ec3620aa34f016d4b210c39d05029 Mon Sep 17 00:00:00 2001
From: Daan De Meyer <daan.j.demeyer@gmail.com>
Date: Sun, 18 Mar 2018 23:57:26 +0100
Subject: [PATCH] Add SHA256 hashes of LLVM downloads and check them when
 downloading LLVM

---
 .../LLVM-5.0.1-win64.exe.SHA256               |  1 +
 .../LLVM-6.0.0-win64.exe.SHA256               |  1 +
 ....0.1-amd64-unknown-freebsd10.tar.xz.SHA256 |  1 +
 ...vm-5.0.1-x86_64-apple-darwin.tar.xz.SHA256 |  1 +
 ...86_64-linux-gnu-ubuntu-14.04.tar.xz.SHA256 |  1 +
 ...0.0-amd64-unknown-freebsd-10.tar.xz.SHA256 |  1 +
 ...vm-6.0.0-x86_64-apple-darwin.tar.xz.SHA256 |  1 +
 ...86_64-linux-gnu-ubuntu-14.04.tar.xz.SHA256 |  1 +
 cmake/DownloadAndExtractLLVM.cmake            | 49 +++++++++++++------
 9 files changed, 43 insertions(+), 14 deletions(-)
 create mode 100644 clang_archive_hashes/LLVM-5.0.1-win64.exe.SHA256
 create mode 100644 clang_archive_hashes/LLVM-6.0.0-win64.exe.SHA256
 create mode 100644 clang_archive_hashes/clang+llvm-5.0.1-amd64-unknown-freebsd10.tar.xz.SHA256
 create mode 100644 clang_archive_hashes/clang+llvm-5.0.1-x86_64-apple-darwin.tar.xz.SHA256
 create mode 100644 clang_archive_hashes/clang+llvm-5.0.1-x86_64-linux-gnu-ubuntu-14.04.tar.xz.SHA256
 create mode 100644 clang_archive_hashes/clang+llvm-6.0.0-amd64-unknown-freebsd-10.tar.xz.SHA256
 create mode 100644 clang_archive_hashes/clang+llvm-6.0.0-x86_64-apple-darwin.tar.xz.SHA256
 create mode 100644 clang_archive_hashes/clang+llvm-6.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz.SHA256

diff --git a/clang_archive_hashes/LLVM-5.0.1-win64.exe.SHA256 b/clang_archive_hashes/LLVM-5.0.1-win64.exe.SHA256
new file mode 100644
index 00000000..ed1e6cf3
--- /dev/null
+++ b/clang_archive_hashes/LLVM-5.0.1-win64.exe.SHA256
@@ -0,0 +1 @@
+981543611d719624acb29a2cffd6a479cff36e8ab5ee8a57d8eca4f9c4c6956f
diff --git a/clang_archive_hashes/LLVM-6.0.0-win64.exe.SHA256 b/clang_archive_hashes/LLVM-6.0.0-win64.exe.SHA256
new file mode 100644
index 00000000..ce28c29a
--- /dev/null
+++ b/clang_archive_hashes/LLVM-6.0.0-win64.exe.SHA256
@@ -0,0 +1 @@
+2501887b2f638d3f65b0336f354b96f8108b563522d81e841d5c88c34af283dd
diff --git a/clang_archive_hashes/clang+llvm-5.0.1-amd64-unknown-freebsd10.tar.xz.SHA256 b/clang_archive_hashes/clang+llvm-5.0.1-amd64-unknown-freebsd10.tar.xz.SHA256
new file mode 100644
index 00000000..4586d17f
--- /dev/null
+++ b/clang_archive_hashes/clang+llvm-5.0.1-amd64-unknown-freebsd10.tar.xz.SHA256
@@ -0,0 +1 @@
+86148b850e78aff743e7aaac337a3a94e9ad16d59ee6629a5ff699c31a73c55b
diff --git a/clang_archive_hashes/clang+llvm-5.0.1-x86_64-apple-darwin.tar.xz.SHA256 b/clang_archive_hashes/clang+llvm-5.0.1-x86_64-apple-darwin.tar.xz.SHA256
new file mode 100644
index 00000000..b61fe520
--- /dev/null
+++ b/clang_archive_hashes/clang+llvm-5.0.1-x86_64-apple-darwin.tar.xz.SHA256
@@ -0,0 +1 @@
+c5b105c4960619feb32641ef051fa39ecb913cc0feb6bacebdfa71f8d3cae277
diff --git a/clang_archive_hashes/clang+llvm-5.0.1-x86_64-linux-gnu-ubuntu-14.04.tar.xz.SHA256 b/clang_archive_hashes/clang+llvm-5.0.1-x86_64-linux-gnu-ubuntu-14.04.tar.xz.SHA256
new file mode 100644
index 00000000..5ea09845
--- /dev/null
+++ b/clang_archive_hashes/clang+llvm-5.0.1-x86_64-linux-gnu-ubuntu-14.04.tar.xz.SHA256
@@ -0,0 +1 @@
+9e61c6669991e2f0d065348c95917b2c6b697d75098b60ec1c2e9f17093ce012
diff --git a/clang_archive_hashes/clang+llvm-6.0.0-amd64-unknown-freebsd-10.tar.xz.SHA256 b/clang_archive_hashes/clang+llvm-6.0.0-amd64-unknown-freebsd-10.tar.xz.SHA256
new file mode 100644
index 00000000..0cbc9d40
--- /dev/null
+++ b/clang_archive_hashes/clang+llvm-6.0.0-amd64-unknown-freebsd-10.tar.xz.SHA256
@@ -0,0 +1 @@
+fee8352f5dee2e38fa2bb80ab0b5ef9efef578cbc6892e5c724a1187498119b7
diff --git a/clang_archive_hashes/clang+llvm-6.0.0-x86_64-apple-darwin.tar.xz.SHA256 b/clang_archive_hashes/clang+llvm-6.0.0-x86_64-apple-darwin.tar.xz.SHA256
new file mode 100644
index 00000000..1d30f273
--- /dev/null
+++ b/clang_archive_hashes/clang+llvm-6.0.0-x86_64-apple-darwin.tar.xz.SHA256
@@ -0,0 +1 @@
+0ef8e99e9c9b262a53ab8f2821e2391d041615dd3f3ff36fdf5370916b0f4268
diff --git a/clang_archive_hashes/clang+llvm-6.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz.SHA256 b/clang_archive_hashes/clang+llvm-6.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz.SHA256
new file mode 100644
index 00000000..e5838317
--- /dev/null
+++ b/clang_archive_hashes/clang+llvm-6.0.0-x86_64-linux-gnu-ubuntu-14.04.tar.xz.SHA256
@@ -0,0 +1 @@
+114e78b2f6db61aaee314c572e07b0d635f653adc5d31bd1cd0bf31a3db4a6e5
diff --git a/cmake/DownloadAndExtractLLVM.cmake b/cmake/DownloadAndExtractLLVM.cmake
index ad285641..83f82b96 100644
--- a/cmake/DownloadAndExtractLLVM.cmake
+++ b/cmake/DownloadAndExtractLLVM.cmake
@@ -1,6 +1,6 @@
 # Downloads and extracts the LLVM archive for the current system from
 # https://releases.llvm.org
-# 
+#
 # Returns the extracted LLVM archive directory in DOWNLOADED_CLANG_DIR
 #
 # Downloads 7-Zip to extract LLVM if it isn't available in the PATH
@@ -12,13 +12,8 @@ set(CLANG_ARCHIVE_EXT .tar.xz)
 
 if(${CMAKE_SYSTEM_NAME} STREQUAL Linux)
 
-  if(${CLANG_VERSION} STREQUAL 5.0.0)
-    set(CLANG_ARCHIVE_NAME 
-        clang+llvm-${CLANG_VERSION}-linux-x86_64-ubuntu14.04)
-  else()
-    set(CLANG_ARCHIVE_NAME 
-        clang+llvm-${CLANG_VERSION}-x86_64-linux-gnu-ubuntu-14.04)
-  endif()
+  set(CLANG_ARCHIVE_NAME
+      clang+llvm-${CLANG_VERSION}-x86_64-linux-gnu-ubuntu-14.04)
 
 elseif(${CMAKE_SYSTEM_NAME} STREQUAL Darwin)
 
@@ -39,19 +34,45 @@ elseif(${CMAKE_SYSTEM_NAME} STREQUAL FreeBSD)
 endif()
 
 if(NOT CLANG_ARCHIVE_NAME)
-  message(FATAL_ERROR "No download available for ${CMAKE_SYSTEM_NAME} + \ 
-${CLANG_VERSION}")
+  message(FATAL_ERROR "No LLVM archive url specified for current platform \
+(${CMAKE_SYSTEM_NAME}). Please file an issue to get it added.")
 endif()
 
 set(CLANG_ARCHIVE_FULL_NAME ${CLANG_ARCHIVE_NAME}${CLANG_ARCHIVE_EXT})
 set(CLANG_ARCHIVE_FILE ${CMAKE_BINARY_DIR}/${CLANG_ARCHIVE_FULL_NAME})
 set(CLANG_ARCHIVE_EXTRACT_DIR ${CMAKE_BINARY_DIR}/${CLANG_ARCHIVE_NAME})
-set(CLANG_ARCHIVE_URL 
+set(CLANG_ARCHIVE_URL
     https://releases.llvm.org/${CLANG_VERSION}/${CLANG_ARCHIVE_FULL_NAME})
+set(CLANG_ARCHIVE_HASH_FILE
+    ${CMAKE_SOURCE_DIR}/clang_archive_hashes/${CLANG_ARCHIVE_FULL_NAME}.SHA256)
+
+if(NOT EXISTS ${CLANG_ARCHIVE_HASH_FILE})
+  message(FATAL_ERROR "No SHA256 hash available for the current platform \
+(${CMAKE_SYSTEM_NAME}) + clang version (${CLANG_VERSION}) combination. Please \
+file an issue to get it added.")
+endif()
+
+file(READ ${CLANG_ARCHIVE_HASH_FILE} CLANG_ARCHIVE_EXPECTED_HASH)
+# Strip newline
+string(STRIP ${CLANG_ARCHIVE_EXPECTED_HASH} CLANG_ARCHIVE_EXPECTED_HASH)
 
 if(NOT EXISTS ${CLANG_ARCHIVE_FILE})
   message(STATUS "Downloading LLVM ${CLANG_VERSION} (${CLANG_ARCHIVE_URL}) ...")
-  file(DOWNLOAD ${CLANG_ARCHIVE_URL} ${CLANG_ARCHIVE_FILE})
+  file(DOWNLOAD ${CLANG_ARCHIVE_URL} ${CLANG_ARCHIVE_FILE}
+       STATUS CLANG_ARCHIVE_DOWNLOAD_RESULT)
+
+  list(GET ${CLANG_ARCHIVE_DOWNLOAD_RESULT} 0 ERROR_CODE)
+  if(${ERROR_CODE})
+    list(GET ${CLANG_ARCHIVE_DOWNLOAD_RESULT} 1 ERROR_STRING)
+    message(FATAL_ERROR ${ERROR_STRING})
+  endif()
+endif()
+
+file(SHA256 ${CLANG_ARCHIVE_FILE} CLANG_ARCHIVE_HASH)
+if(NOT ${CLANG_ARCHIVE_EXPECTED_HASH} STREQUAL ${CLANG_ARCHIVE_HASH})
+  message(FATAL_ERROR "SHA256 hash of downloaded LLVM does not match \
+expected hash. Remove the build directory and try running CMake again. If this \
+keeps happening, file an issue to report the problem.")
 endif()
 
 if(NOT EXISTS ${CLANG_ARCHIVE_EXTRACT_DIR})
@@ -61,7 +82,7 @@ if(NOT EXISTS ${CLANG_ARCHIVE_EXTRACT_DIR})
     if(NOT 7ZIP_EXECUTABLE)
       message(STATUS "7-Zip not found in PATH")
       download_and_extract_7zip()
-      find_program(7ZIP_EXECUTABLE 7z NO_DEFAULT_PATH 
+      find_program(7ZIP_EXECUTABLE 7z NO_DEFAULT_PATH
                    PATHS ${DOWNLOADED_7ZIP_DIR})
     else()
       message(STATUS "7-Zip found in PATH")
@@ -70,7 +91,7 @@ if(NOT EXISTS ${CLANG_ARCHIVE_EXTRACT_DIR})
     message(STATUS "Extracting downloaded LLVM with 7-Zip ...")
 
     # Avoid running the LLVM installer by extracting the exe with 7-Zip
-    execute_process(COMMAND ${7ZIP_EXECUTABLE} x 
+    execute_process(COMMAND ${7ZIP_EXECUTABLE} x
                             -o${CLANG_ARCHIVE_EXTRACT_DIR}
                             -xr!$PLUGINSDIR ${CLANG_ARCHIVE_FILE}
                     OUTPUT_QUIET)