]> granicus.if.org Git - llvm/commitdiff
[libFuzzer] Avoid undefined behavior, properly discard output to stdout/stderr.
authorMarcos Pividori <mpividori@google.com>
Sun, 22 Jan 2017 01:58:45 +0000 (01:58 +0000)
committerMarcos Pividori <mpividori@google.com>
Sun, 22 Jan 2017 01:58:45 +0000 (01:58 +0000)
Fix libFuzzer when setting -close_fd_mask to a non-zero value.
In previous implementation, libFuzzer closes the file descriptors for
stdout/stderr. This has some disavantages:

For `fuzzer-fdmask.test`, we write directly to stdout and stderr using the
file streams stdout and stderr, after the file descriptors are closed, which is
undefined behavior. In Windows, in particular, this was making the test fail.

Also, if we close stdout and we open a new file in libFuzzer, we get the file
descriptor 1, which could generate problem if some code assumes file descriptors
refers to stdout and works directly writing to the file descriptor 1, but it
will be writing to the opened file (for example using std::cout).

Instead of closing the file descriptors, I redirect the output to /dev/null on
linux and nul on Windows.

Differential Revision: https://reviews.llvm.org/D28718

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@292743 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Fuzzer/FuzzerIO.cpp
lib/Fuzzer/FuzzerIO.h
lib/Fuzzer/FuzzerIOPosix.cpp
lib/Fuzzer/FuzzerIOWindows.cpp

index eda8e8772930001dc5ccdd6f221e5b8f2839263a..45445fa3ba41af2602ea165d8178abd5b59fea91 100644 (file)
@@ -97,13 +97,13 @@ void DupAndCloseStderr() {
       OutputFile = NewOutputFile;
       if (EF->__sanitizer_set_report_fd)
         EF->__sanitizer_set_report_fd(reinterpret_cast<void *>(OutputFd));
-      CloseFile(2);
+      DiscardOutput(2);
     }
   }
 }
 
 void CloseStdout() {
-  CloseFile(1);
+  DiscardOutput(1);
 }
 
 void Printf(const char *Fmt, ...) {
index 17cf2ab6ac14720836f5a9097fb6544ac26c4db0..1f79f3632baf2d1700fd2fa4a0b4dd6d139a6e3c 100644 (file)
@@ -64,6 +64,8 @@ int DuplicateFile(int Fd);
 
 void RemoveFile(const std::string &Path);
 
+void DiscardOutput(int Fd);
+
 }  // namespace fuzzer
 
 #endif  // LLVM_FUZZER_IO_H
index 494ec9e6c8336d5f1a93fe9c90f894c7fde4bae3..2dc2c61b9990acce128371a9973ce516d4736b01 100644 (file)
@@ -75,6 +75,14 @@ void RemoveFile(const std::string &Path) {
   unlink(Path.c_str());
 }
 
+void DiscardOutput(int Fd) {
+  FILE* Temp = fopen("/dev/null", "w");
+  if (!Temp)
+    return;
+  dup2(fileno(Temp), Fd);
+  fclose(Temp);
+}
+
 std::string DirName(const std::string &FileName) {
   char *Tmp = new char[FileName.size() + 1];
   memcpy(Tmp, FileName.c_str(), FileName.size() + 1);
index 983cb6c2e4a125a577ff99878922f58171eccba3..1d82f416272da1d6104a7e35610d2384d2586084 100644 (file)
@@ -141,6 +141,14 @@ void RemoveFile(const std::string &Path) {
   _unlink(Path.c_str());
 }
 
+void DiscardOutput(int Fd) {
+  FILE* Temp = fopen("nul", "w");
+  if (!Temp)
+    return;
+  _dup2(_fileno(Temp), Fd);
+  fclose(Temp);
+}
+
 static bool IsSeparator(char C) {
   return C == '\\' || C == '/';
 }