From 4967ccc054d268c430e73445f3a103e737c5f5f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?D=C4=81vis=20Mos=C4=81ns?= <davispuh@gmail.com>
Date: Wed, 9 Nov 2016 23:27:53 +0200
Subject: [PATCH] ConsoleBuf: Fix output for strings that contain null byte

Change-Id: I941dcebe0193112f0d5aaf77cac55246febe4d3c
---
 ConsoleBuf.hxx.in       |  5 ++---
 testConsoleBuf.cxx      | 33 ++++++++++++++++++++++++---------
 testConsoleBuf.hxx      |  2 +-
 testConsoleBufChild.cxx |  3 ++-
 4 files changed, 29 insertions(+), 14 deletions(-)

diff --git a/ConsoleBuf.hxx.in b/ConsoleBuf.hxx.in
index c45a351..cb58865 100644
--- a/ConsoleBuf.hxx.in
+++ b/ConsoleBuf.hxx.in
@@ -327,14 +327,13 @@ private:
     const int length =
       WideCharToMultiByte(m_activeOutputCodepage, 0, wbuffer.c_str(),
                           (int)wbuffer.size(), NULL, 0, NULL, NULL);
-    char* buf = new char[length + 1];
+    char* buf = new char[length];
     const bool success =
       WideCharToMultiByte(m_activeOutputCodepage, 0, wbuffer.c_str(),
                           (int)wbuffer.size(), buf, length, NULL, NULL) > 0
       ? true
       : false;
-    buf[length] = '\0';
-    buffer = buf;
+    buffer = std::string(buf, length);
     delete[] buf;
     return success;
   }
diff --git a/testConsoleBuf.cxx b/testConsoleBuf.cxx
index bd58fb6..3b8cdab 100644
--- a/testConsoleBuf.cxx
+++ b/testConsoleBuf.cxx
@@ -18,6 +18,7 @@
 
 #if defined(_WIN32)
 
+#include <algorithm>
 #include <iomanip>
 #include <iostream>
 #include <stdexcept>
@@ -318,6 +319,7 @@ static int testPipe()
             bytesRead == 0) {
           throw std::runtime_error("ReadFile#1 failed!");
         }
+        buffer[bytesRead] = 0;
         if ((bytesRead <
                encodedTestString.size() + 1 + encodedInputTestString.size() &&
              !ReadFile(outPipeRead, buffer + bytesRead,
@@ -336,8 +338,12 @@ static int testPipe()
               bytesRead == 0) {
             throw std::runtime_error("ReadFile#3 failed!");
           }
-          buffer2[bytesRead - 1] = 0;
-          didFail = encodedTestString.compare(buffer2) == 0 ? 0 : 1;
+          buffer2[bytesRead] = 0;
+          didFail =
+            encodedTestString.compare(0, encodedTestString.npos, buffer2,
+                                      encodedTestString.size()) == 0
+            ? 0
+            : 1;
         }
         if (didFail != 0) {
           std::cerr << "Pipe's output didn't match expected output!"
@@ -423,23 +429,28 @@ static int testFile()
             bytesRead == 0) {
           throw std::runtime_error("ReadFile#1 failed!");
         }
-        buffer[bytesRead - 1] = 0;
+        buffer[bytesRead] = 0;
         if (memcmp(buffer, encodedTestString.c_str(),
                    encodedTestString.size()) == 0 &&
             memcmp(buffer + encodedTestString.size() + 1,
                    encodedInputTestString.c_str(),
-                   encodedInputTestString.size() - 1) == 0) {
+                   encodedInputTestString.size()) == 0) {
           bytesRead = 0;
           if (SetFilePointer(errFile, 0, 0, FILE_BEGIN) ==
               INVALID_SET_FILE_POINTER) {
             throw std::runtime_error("SetFilePointer#2 failed!");
           }
+
           if (!ReadFile(errFile, buffer2, sizeof(buffer2), &bytesRead, NULL) ||
               bytesRead == 0) {
             throw std::runtime_error("ReadFile#2 failed!");
           }
-          buffer2[bytesRead - 1] = 0;
-          didFail = encodedTestString.compare(buffer2) == 0 ? 0 : 1;
+          buffer2[bytesRead] = 0;
+          didFail =
+            encodedTestString.compare(0, encodedTestString.npos, buffer2,
+                                      encodedTestString.size()) == 0
+            ? 0
+            : 1;
         }
         if (didFail != 0) {
           std::cerr << "File's output didn't match expected output!"
@@ -448,7 +459,7 @@ static int testFile()
                             encodedTestString.size());
           dumpBuffers<char>(encodedInputTestString.c_str(),
                             buffer + encodedTestString.size() + 1,
-                            encodedInputTestString.size() - 1);
+                            encodedInputTestString.size());
           dumpBuffers<char>(encodedTestString.c_str(), buffer2,
                             encodedTestString.size());
         }
@@ -685,6 +696,7 @@ static int testConsole()
         throw std::runtime_error("ReadConsoleOutputCharacter failed!");
       }
       std::wstring wideTestString = kwsys::Encoding::ToWide(encodedTestString);
+      std::replace(wideTestString.begin(), wideTestString.end(), '\0', ' ');
       std::wstring wideInputTestString =
         kwsys::Encoding::ToWide(encodedInputTestString);
       if (memcmp(outputBuffer, wideTestString.c_str(),
@@ -757,8 +769,11 @@ int testConsoleBuf(int, char* [])
     return 1;
   }
 
-  encodedTestString = kwsys::Encoding::ToNarrow(UnicodeTestString);
-  encodedInputTestString = kwsys::Encoding::ToNarrow(UnicodeInputTestString);
+  encodedTestString = kwsys::Encoding::ToNarrow(std::wstring(
+    UnicodeTestString, sizeof(UnicodeTestString) / sizeof(wchar_t) - 1));
+  encodedInputTestString = kwsys::Encoding::ToNarrow(
+    std::wstring(UnicodeInputTestString,
+                 sizeof(UnicodeInputTestString) / sizeof(wchar_t) - 1));
   encodedInputTestString += "\n";
 
   ret |= testPipe();
diff --git a/testConsoleBuf.hxx b/testConsoleBuf.hxx
index 8891960..e93cb4f 100644
--- a/testConsoleBuf.hxx
+++ b/testConsoleBuf.hxx
@@ -11,7 +11,7 @@ static const wchar_t AfterOutputEventName[] = L"AfterOutputEvent";
 // यूनिकोड είναι здорово!
 static const wchar_t UnicodeTestString[] =
   L"\u092F\u0942\u0928\u093F\u0915\u094B\u0921 "
-  L"\u03B5\u03AF\u03BD\u03B1\u03B9 "
+  L"\u03B5\u03AF\u03BD\0\u03B1\u03B9 "
   L"\u0437\u0434\u043E\u0440\u043E\u0432\u043E!";
 
 #endif
diff --git a/testConsoleBufChild.cxx b/testConsoleBufChild.cxx
index 313323e..83bf545 100644
--- a/testConsoleBufChild.cxx
+++ b/testConsoleBufChild.cxx
@@ -28,7 +28,8 @@ int main(int argc, const char* argv[])
     std::cout << argv[1] << std::endl;
     std::cerr << argv[1] << std::endl;
   } else {
-    std::string str = kwsys::Encoding::ToNarrow(UnicodeTestString);
+    std::string str = kwsys::Encoding::ToNarrow(std::wstring(
+      UnicodeTestString, sizeof(UnicodeTestString) / sizeof(wchar_t) - 1));
     std::cout << str << std::endl;
     std::cerr << str << std::endl;
   }
-- 
GitLab