From 90b4d1bcb20180c591385131b12fa90d2e4860b1 Mon Sep 17 00:00:00 2001 From: Roy Sundahl Date: Wed, 15 Mar 2023 18:56:11 -0700 Subject: [PATCH] [fuzzer] Use puts() rather than printf() in CopyFileToErr() CopyFileToErr() uses Printf("%s", ...) which fails with a negative size on files >2Gb (Its path is through var-args wrappers to an unnecessary "%s" expansion and subject to int overflows) Using puts() in place of printf() bypasses this path and writes the string directly to stderr. This avoids the present loss of data when a crashed worker has generated >2Gb of output. rdar://99384640 Reviewed By: yln, rsundahl Differential Revision: https://reviews.llvm.org/D146189 --- compiler-rt/lib/fuzzer/FuzzerIO.cpp | 7 ++++- compiler-rt/lib/fuzzer/FuzzerIO.h | 1 + compiler-rt/test/fuzzer/BigFileCopy.cpp | 31 ++++++++++++++++++++++ compiler-rt/test/fuzzer/big-file-copy.test | 4 +++ 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 compiler-rt/test/fuzzer/BigFileCopy.cpp create mode 100644 compiler-rt/test/fuzzer/big-file-copy.test diff --git a/compiler-rt/lib/fuzzer/FuzzerIO.cpp b/compiler-rt/lib/fuzzer/FuzzerIO.cpp index 0a58c5377b34f..54cc4ee54be0a 100644 --- a/compiler-rt/lib/fuzzer/FuzzerIO.cpp +++ b/compiler-rt/lib/fuzzer/FuzzerIO.cpp @@ -65,7 +65,7 @@ std::string FileToString(const std::string &Path) { } void CopyFileToErr(const std::string &Path) { - Printf("%s", FileToString(Path).c_str()); + Puts(FileToString(Path).c_str()); } void WriteToFile(const Unit &U, const std::string &Path) { @@ -151,6 +151,11 @@ void CloseStdout() { DiscardOutput(1); } +void Puts(const char *Str) { + fputs(Str, OutputFile); + fflush(OutputFile); +} + void Printf(const char *Fmt, ...) { va_list ap; va_start(ap, Fmt); diff --git a/compiler-rt/lib/fuzzer/FuzzerIO.h b/compiler-rt/lib/fuzzer/FuzzerIO.h index 401afa0b44773..874caad1baedb 100644 --- a/compiler-rt/lib/fuzzer/FuzzerIO.h +++ b/compiler-rt/lib/fuzzer/FuzzerIO.h @@ -58,6 +58,7 @@ void CloseStdout(); FILE *GetOutputFile(); void SetOutputFile(FILE *NewOutputFile); +void Puts(const char *Str); void Printf(const char *Fmt, ...); void VPrintf(bool Verbose, const char *Fmt, ...); diff --git a/compiler-rt/test/fuzzer/BigFileCopy.cpp b/compiler-rt/test/fuzzer/BigFileCopy.cpp new file mode 100644 index 0000000000000..5515365246b44 --- /dev/null +++ b/compiler-rt/test/fuzzer/BigFileCopy.cpp @@ -0,0 +1,31 @@ +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +#include "FuzzerIO.h" + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + const char *FileName = "big-file.txt"; + FILE *f = fopen(FileName, "w"); + + // This is the biggest file possible unless CopyFileToErr() uses Puts() + fprintf(f, "%2147483646s", "2Gb-2"); + + // This makes the file too big if CopyFileToErr() uses fprintf("%s", ) + fprintf(f, "THIS LINE RESPONSIBLE FOR EXCEEDING 2Gb FILE SIZE\n"); + fclose(f); + + // Should now because CopyFileToErr() now uses Puts() + fuzzer::CopyFileToErr(FileName); + + // File is >2Gb so clean up + remove(FileName); + + return 0; +} diff --git a/compiler-rt/test/fuzzer/big-file-copy.test b/compiler-rt/test/fuzzer/big-file-copy.test new file mode 100644 index 0000000000000..2a9f3616ad1e8 --- /dev/null +++ b/compiler-rt/test/fuzzer/big-file-copy.test @@ -0,0 +1,4 @@ +RUN: %cpp_compiler %S/BigFileCopy.cpp -o %t +RUN: %run %t -runs=1 -rss_limit_mb=4096 2>big-file-out.txt; result=$? +RUN: %run rm -f big-file.txt big-file-out.txt +RUN: %run (exit $result)