/src/mozilla-central/tools/fuzzing/libfuzzer/FuzzerDataFlowTrace.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- FuzzerDataFlowTrace.cpp - DataFlowTrace ---*- C++ -* ===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | // fuzzer::DataFlowTrace |
10 | | //===----------------------------------------------------------------------===// |
11 | | |
12 | | #include "FuzzerDataFlowTrace.h" |
13 | | #include "FuzzerIO.h" |
14 | | |
15 | | #include <cstdlib> |
16 | | #include <fstream> |
17 | | #include <string> |
18 | | #include <vector> |
19 | | |
20 | | namespace fuzzer { |
21 | | |
22 | | void DataFlowTrace::Init(const std::string &DirPath, |
23 | 3 | const std::string &FocusFunction) { |
24 | 3 | if (DirPath.empty()) return; |
25 | 0 | const char *kFunctionsTxt = "functions.txt"; |
26 | 0 | Printf("INFO: DataFlowTrace: reading from '%s'\n", DirPath.c_str()); |
27 | 0 | Vector<SizedFile> Files; |
28 | 0 | GetSizedFilesFromDir(DirPath, &Files); |
29 | 0 | std::string L; |
30 | 0 |
|
31 | 0 | // Read functions.txt |
32 | 0 | std::ifstream IF(DirPlusFile(DirPath, kFunctionsTxt)); |
33 | 0 | size_t FocusFuncIdx = SIZE_MAX; |
34 | 0 | size_t NumFunctions = 0; |
35 | 0 | while (std::getline(IF, L, '\n')) { |
36 | 0 | NumFunctions++; |
37 | 0 | if (FocusFunction == L) |
38 | 0 | FocusFuncIdx = NumFunctions - 1; |
39 | 0 | } |
40 | 0 | if (!NumFunctions || FocusFuncIdx == SIZE_MAX || Files.size() <= 1) |
41 | 0 | return; |
42 | 0 | // Read traces. |
43 | 0 | size_t NumTraceFiles = 0; |
44 | 0 | size_t NumTracesWithFocusFunction = 0; |
45 | 0 | for (auto &SF : Files) { |
46 | 0 | auto Name = Basename(SF.File); |
47 | 0 | if (Name == kFunctionsTxt) continue; |
48 | 0 | auto ParseError = [&](const char *Err) { |
49 | 0 | Printf("DataFlowTrace: parse error: %s\n File: %s\n Line: %s\n", Err, |
50 | 0 | Name.c_str(), L.c_str()); |
51 | 0 | }; |
52 | 0 | NumTraceFiles++; |
53 | 0 | // Printf("=== %s\n", Name.c_str()); |
54 | 0 | std::ifstream IF(SF.File); |
55 | 0 | while (std::getline(IF, L, '\n')) { |
56 | 0 | size_t SpacePos = L.find(' '); |
57 | 0 | if (SpacePos == std::string::npos) |
58 | 0 | return ParseError("no space in the trace line"); |
59 | 0 | if (L.empty() || L[0] != 'F') |
60 | 0 | return ParseError("the trace line doesn't start with 'F'"); |
61 | 0 | size_t N = std::atol(L.c_str() + 1); |
62 | 0 | if (N >= NumFunctions) |
63 | 0 | return ParseError("N is greater than the number of functions"); |
64 | 0 | if (N == FocusFuncIdx) { |
65 | 0 | NumTracesWithFocusFunction++; |
66 | 0 | const char *Beg = L.c_str() + SpacePos + 1; |
67 | 0 | const char *End = L.c_str() + L.size(); |
68 | 0 | assert(Beg < End); |
69 | 0 | size_t Len = End - Beg; |
70 | 0 | Vector<uint8_t> V(Len); |
71 | 0 | for (size_t I = 0; I < Len; I++) { |
72 | 0 | if (Beg[I] != '0' && Beg[I] != '1') |
73 | 0 | ParseError("the trace should contain only 0 or 1"); |
74 | 0 | V[I] = Beg[I] == '1'; |
75 | 0 | } |
76 | 0 | Traces[Name] = V; |
77 | 0 | // Print just a few small traces. |
78 | 0 | if (NumTracesWithFocusFunction <= 3 && Len <= 16) |
79 | 0 | Printf("%s => |%s|\n", Name.c_str(), L.c_str() + SpacePos + 1); |
80 | 0 | break; // No need to parse the following lines. |
81 | 0 | } |
82 | 0 | } |
83 | 0 | } |
84 | 0 | assert(NumTraceFiles == Files.size() - 1); |
85 | 0 | Printf("INFO: DataFlowTrace: %zd trace files, %zd functions, " |
86 | 0 | "%zd traces with focus function\n", |
87 | 0 | NumTraceFiles, NumFunctions, NumTracesWithFocusFunction); |
88 | 0 | } |
89 | | |
90 | | } // namespace fuzzer |
91 | | |