HDFS-15955. Make explicit_bzero cross platform (#2875)

diff --git a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/bindings/c/hdfs.cc b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/bindings/c/hdfs.cc
index efa4c75..80f9316 100644
--- a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/bindings/c/hdfs.cc
+++ b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/bindings/c/hdfs.cc
@@ -25,6 +25,7 @@
 #include "fs/filesystem.h"
 #include "fs/filehandle.h"
 #include "x-platform/utils.h"
+#include "x-platform/syscall.h"
 
 #include <limits.h>
 #include <string>
@@ -1395,7 +1396,7 @@
     hdfsBlockLocations *locations = new struct hdfsBlockLocations();
     (*locations_out) = locations;
 
-    explicit_bzero(locations, sizeof(*locations));
+    XPlatform::Syscall::ClearBufferSafely(locations, sizeof(*locations));
     locations->fileLength = ppLocations->getFileLength();
     locations->isLastBlockComplete = ppLocations->isLastBlockComplete();
     locations->isUnderConstruction = ppLocations->isUnderConstruction();
diff --git a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/x-platform/syscall.h b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/x-platform/syscall.h
index 297aceb..4f94ecb 100644
--- a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/x-platform/syscall.h
+++ b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/x-platform/syscall.h
@@ -59,6 +59,18 @@
    */
   static bool FnMatch(const std::string& pattern, const std::string& str);
 
+  /**
+   * Clears the given {@link buffer} upto {@link sz_bytes} by
+   * filling them with zeros. This method is immune to compiler
+   * optimizations and guarantees that the first {@link sz_bytes} of
+   * {@link buffer} is cleared. The {@link buffer} must be at least
+   * as big as {@link sz_bytes}, the behaviour is undefined otherwise.
+   *
+   * @param buffer the pointer to the buffer to clear.
+   * @param sz_bytes the count of the bytes to clear.
+   */
+  static void ClearBufferSafely(void* buffer, size_t sz_bytes);
+
  private:
   static bool WriteToStdoutImpl(const char* message);
 };
diff --git a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/x-platform/syscall_linux.cc b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/x-platform/syscall_linux.cc
index 2c51dbf..9821cc7 100644
--- a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/x-platform/syscall_linux.cc
+++ b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/x-platform/syscall_linux.cc
@@ -41,3 +41,10 @@
   const auto result = write(1, message, message_len);
   return result == static_cast<ssize_t>(message_len);
 }
+
+void XPlatform::Syscall::ClearBufferSafely(void* buffer,
+                                           const size_t sz_bytes) {
+  if (buffer != nullptr) {
+    explicit_bzero(buffer, sz_bytes);
+  }
+}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/x-platform/syscall_windows.cc b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/x-platform/syscall_windows.cc
index dc9ba63..5a3423a 100644
--- a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/x-platform/syscall_windows.cc
+++ b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/lib/x-platform/syscall_windows.cc
@@ -17,6 +17,7 @@
  */
 
 #include <Shlwapi.h>
+#include <WinBase.h>
 #include <Windows.h>
 
 #include "syscall.h"
@@ -49,3 +50,10 @@
       WriteFile(stdout_handle, message, message_len, &bytes_written, nullptr);
   return result && static_cast<unsigned long>(message_len) == bytes_written;
 }
+
+void XPlatform::Syscall::ClearBufferSafely(void* buffer,
+                                           const size_t sz_bytes) {
+  if (buffer != nullptr) {
+    SecureZeroMemory(buffer, sz_bytes);
+  }
+}
diff --git a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/hdfs_ext_test.cc b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/hdfs_ext_test.cc
index fb55172..34e5384 100644
--- a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/hdfs_ext_test.cc
+++ b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/hdfs_ext_test.cc
@@ -18,6 +18,7 @@
 
 #include "hdfspp_mini_dfs.h"
 #include "hdfspp/hdfs_ext.h"
+#include "x-platform/syscall.h"
 
 #include <cstring>
 #include <chrono>
@@ -475,7 +476,7 @@
   hdfsFile file = hdfsOpenFile(fs, path.c_str(), O_WRONLY, 0, 0, 0);
   EXPECT_NE(nullptr, file);
   void * buf = malloc(size);
-  explicit_bzero(buf, size);
+  XPlatform::Syscall::ClearBufferSafely(buf, size);
   EXPECT_EQ(size, hdfsWrite(fs, file, buf, size));
   free(buf);
   EXPECT_EQ(0, hdfsCloseFile(fs, file));
diff --git a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/hdfspp_mini_dfs.h b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/hdfspp_mini_dfs.h
index 98edbdc..aae8d83 100644
--- a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/hdfspp_mini_dfs.h
+++ b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/hdfspp_mini_dfs.h
@@ -19,6 +19,7 @@
 #include "hdfs/hdfs.h"
 #include "hdfspp/hdfspp.h"
 #include <native_mini_dfs.h>
+#include "x-platform/syscall.h"
 
 #include <google/protobuf/io/coded_stream.h>
 #include <gmock/gmock.h>
@@ -92,7 +93,7 @@
     hdfsFile file = hdfsOpenFile(*this, path.c_str(), O_WRONLY, 0, 0, 0);
     EXPECT_NE(nullptr, file);
     void * buf = malloc(size);
-    explicit_bzero(buf, size);
+    XPlatform::Syscall::ClearBufferSafely(buf, size);
     EXPECT_EQ(1024, hdfsWrite(*this, file, buf, size));
     EXPECT_EQ(0, hdfsCloseFile(*this, file));
     free(buf);
diff --git a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/x-platform/syscall_common_test.cc b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/x-platform/syscall_common_test.cc
index 04da29a..d68b2af 100644
--- a/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/x-platform/syscall_common_test.cc
+++ b/hadoop-hdfs-project/hadoop-hdfs-native-client/src/main/native/libhdfspp/tests/x-platform/syscall_common_test.cc
@@ -18,7 +18,9 @@
 
 #include <gtest/gtest.h>
 
+#include <numeric>
 #include <string>
+#include <vector>
 
 #include "x-platform/syscall.h"
 
@@ -45,3 +47,24 @@
   const std::string str("abc.doc");
   EXPECT_FALSE(XPlatform::Syscall::FnMatch(pattern, str));
 }
+
+TEST(XPlatformSyscall, ClearBufferSafelyChars) {
+  std::vector<char> alphabets(26);
+  std::iota(alphabets.begin(), alphabets.end(), 'a');
+
+  XPlatform::Syscall::ClearBufferSafely(alphabets.data(), alphabets.size());
+  for (const auto alphabet : alphabets) {
+    EXPECT_EQ(alphabet, '\0');
+  }
+}
+
+TEST(XPlatformSyscall, ClearBufferSafelyNumbers) {
+  std::vector<int> numbers(200);
+  std::iota(numbers.begin(), numbers.end(), 0);
+
+  XPlatform::Syscall::ClearBufferSafely(numbers.data(),
+                                        numbers.size() * sizeof(int));
+  for (const auto number : numbers) {
+    EXPECT_EQ(number, 0);
+  }
+}
\ No newline at end of file