Skip to content

Commit

Permalink
[fuzzer] Use puts() rather than printf() in CopyFileToErr()
Browse files Browse the repository at this point in the history
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
  • Loading branch information
rsundahl committed Mar 28, 2023
1 parent 2fe49ea commit 90b4d1b
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 1 deletion.
7 changes: 6 additions & 1 deletion compiler-rt/lib/fuzzer/FuzzerIO.cpp
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions compiler-rt/lib/fuzzer/FuzzerIO.h
Expand Up @@ -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, ...);

Expand Down
31 changes: 31 additions & 0 deletions 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 <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#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", <file>)
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;
}
4 changes: 4 additions & 0 deletions 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)

0 comments on commit 90b4d1b

Please sign in to comment.