Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(180)

Side by Side Diff: courgette/encoded_program_fuzz_unittest.cc

Issue 2827103002: [Courgette] Refactor: Add CourgetteFlow; improve courgette_tool.cc help text. (Closed)
Patch Set: Add virtual destructor to BasicBuffer and its implementations. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « courgette/encode_decode_unittest.cc ('k') | courgette/patch_generator_x86_32.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // Fuzz testing for EncodedProgram serialized format and assembly. 5 // Fuzz testing for EncodedProgram serialized format and assembly.
6 // 6 //
7 // We would like some assurance that if an EncodedProgram is malformed we will 7 // We would like some assurance that if an EncodedProgram is malformed we will
8 // not crash. The EncodedProgram could be malformed either due to malicious 8 // not crash. The EncodedProgram could be malformed either due to malicious
9 // attack to due to an error in patch generation. 9 // attack to due to an error in patch generation.
10 // 10 //
11 // We try a lot of arbitrary modifications to the serialized form and make sure 11 // We try a lot of arbitrary modifications to the serialized form and make sure
12 // that the outcome is not a crash. 12 // that the outcome is not a crash.
13 #include "courgette/encoded_program.h" 13 #include "courgette/encoded_program.h"
14 14
15 #include <stddef.h> 15 #include <stddef.h>
16 16
17 #include <memory> 17 #include <memory>
18 18
19 #include "base/test/test_suite.h" 19 #include "base/test/test_suite.h"
20 #include "courgette/assembly_program.h"
21 #include "courgette/base_test_unittest.h" 20 #include "courgette/base_test_unittest.h"
22 #include "courgette/courgette.h" 21 #include "courgette/courgette.h"
23 #include "courgette/program_detector.h" 22 #include "courgette/courgette_flow.h"
24 #include "courgette/streams.h" 23 #include "courgette/streams.h"
25 24
26 class DecodeFuzzTest : public BaseTest { 25 class DecodeFuzzTest : public BaseTest {
27 public: 26 public:
28 void FuzzExe(const char *) const; 27 void FuzzExe(const char *) const;
29 28
30 private: 29 private:
31 void FuzzByte(const std::string& buffer, const std::string& output, 30 void FuzzByte(const std::string& buffer, const std::string& output,
32 size_t index) const; 31 size_t index) const;
33 void FuzzBits(const std::string& buffer, const std::string& output, 32 void FuzzBits(const std::string& buffer, const std::string& output,
34 size_t index, int bits_to_flip) const; 33 size_t index, int bits_to_flip) const;
35 34
36 // Returns true if could assemble, false if rejected. 35 // Returns true if could assemble, false if rejected.
37 bool TryAssemble(const std::string& buffer, std::string* output) const; 36 bool TryAssemble(const std::string& buffer, std::string* output) const;
38 }; 37 };
39 38
40 // Loads an executable and does fuzz testing in the serialized format. 39 // Loads an executable and does fuzz testing in the serialized format.
41 void DecodeFuzzTest::FuzzExe(const char* file_name) const { 40 void DecodeFuzzTest::FuzzExe(const char* file_name) const {
42 std::string file1 = FileContents(file_name); 41 std::string file1 = FileContents(file_name);
43 42
44 const uint8_t* original_buffer = 43 const uint8_t* original_data = reinterpret_cast<const uint8_t*>(file1.data());
45 reinterpret_cast<const uint8_t*>(file1.data());
46 size_t original_length = file1.length(); 44 size_t original_length = file1.length();
45 courgette::CourgetteFlow flow;
47 46
48 std::unique_ptr<courgette::AssemblyProgram> program; 47 courgette::RegionBuffer original_buffer(
49 const courgette::Status parse_status = 48 courgette::Region(original_data, original_length));
50 courgette::ParseDetectedExecutable(original_buffer, original_length, 49 flow.ReadAssemblyProgramFromBuffer(flow.ONLY, original_buffer, false);
51 &program); 50 EXPECT_EQ(courgette::C_OK, flow.status());
52 EXPECT_EQ(courgette::C_OK, parse_status); 51 EXPECT_TRUE(nullptr != flow.data(flow.ONLY)->program.get());
53 52
54 std::unique_ptr<courgette::EncodedProgram> encoded; 53 flow.CreateEncodedProgramFromAssemblyProgram(flow.ONLY);
55 const courgette::Status encode_status = Encode(*program, &encoded); 54 EXPECT_EQ(courgette::C_OK, flow.status());
56 EXPECT_EQ(courgette::C_OK, encode_status); 55 EXPECT_TRUE(nullptr != flow.data(flow.ONLY)->encoded.get());
57 56
58 program.reset(); 57 flow.DestroyAssemblyProgram(flow.ONLY);
58 EXPECT_EQ(courgette::C_OK, flow.status());
59 EXPECT_TRUE(nullptr == flow.data(flow.ONLY)->program.get());
59 60
60 courgette::SinkStreamSet sinks; 61 flow.WriteSinkStreamSetFromEncodedProgram(flow.ONLY);
61 const courgette::Status write_status = 62 EXPECT_EQ(courgette::C_OK, flow.status());
62 WriteEncodedProgram(encoded.get(), &sinks);
63 EXPECT_EQ(courgette::C_OK, write_status);
64 63
65 encoded.reset(); 64 flow.DestroyEncodedProgram(flow.ONLY);
65 EXPECT_EQ(courgette::C_OK, flow.status());
66 EXPECT_TRUE(nullptr == flow.data(flow.ONLY)->encoded.get());
66 67
67 courgette::SinkStream sink; 68 courgette::SinkStream sink;
68 bool can_collect = sinks.CopyTo(&sink); 69 flow.WriteSinkStreamFromSinkStreamSet(flow.ONLY, &sink);
69 EXPECT_TRUE(can_collect); 70 EXPECT_EQ(courgette::C_OK, flow.status());
71 EXPECT_TRUE(flow.ok());
72 EXPECT_FALSE(flow.failed());
70 73
71 size_t length = sink.Length(); 74 size_t length = sink.Length();
72 75
73 std::string base_buffer(reinterpret_cast<const char*>(sink.Buffer()), length); 76 std::string base_buffer(reinterpret_cast<const char*>(sink.Buffer()), length);
74 std::string base_output; 77 std::string base_output;
75 bool ok = TryAssemble(base_buffer, &base_output); 78 bool ok = TryAssemble(base_buffer, &base_output);
76 EXPECT_TRUE(ok); 79 EXPECT_TRUE(ok);
77 80
78 // Now we have a good serialized EncodedProgram in |base_buffer|. Time to 81 // Now we have a good serialized EncodedProgram in |base_buffer|. Time to
79 // fuzz. 82 // fuzz.
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 } 169 }
167 170
168 if (index > 60) { // Beyond the origin addresses ... 171 if (index > 60) { // Beyond the origin addresses ...
169 EXPECT_NE(0U, changed_byte_count); // ... we expect some difference. 172 EXPECT_NE(0U, changed_byte_count); // ... we expect some difference.
170 } 173 }
171 // Currently all changes are smaller than this number: 174 // Currently all changes are smaller than this number:
172 EXPECT_GE(45000U, changed_byte_count); 175 EXPECT_GE(45000U, changed_byte_count);
173 } 176 }
174 } 177 }
175 178
176 bool DecodeFuzzTest::TryAssemble(const std::string& buffer, 179 bool DecodeFuzzTest::TryAssemble(const std::string& file,
177 std::string* output) const { 180 std::string* output) const {
178 std::unique_ptr<courgette::EncodedProgram> encoded; 181 courgette::CourgetteFlow flow;
179 bool result = false; 182 courgette::RegionBuffer file_buffer(courgette::Region(
183 reinterpret_cast<const uint8_t*>(file.data()), file.length()));
184 flow.ReadSourceStreamSetFromBuffer(flow.ONLY, file_buffer);
185 if (flow.failed())
186 return false;
180 187
181 courgette::SourceStreamSet sources; 188 flow.ReadEncodedProgramFromSourceStreamSet(flow.ONLY);
182 bool can_get_source_streams = sources.Init(buffer.c_str(), buffer.length()); 189 if (flow.failed())
183 if (can_get_source_streams) { 190 return false;
184 const courgette::Status read_status =
185 ReadEncodedProgram(&sources, &encoded);
186 if (read_status == courgette::C_OK) {
187 courgette::SinkStream assembled;
188 const courgette::Status assemble_status =
189 Assemble(encoded.get(), &assembled);
190 191
191 if (assemble_status == courgette::C_OK) { 192 courgette::SinkStream sink;
192 const void* assembled_buffer = assembled.Buffer(); 193 flow.WriteExecutableFromEncodedProgram(flow.ONLY, &sink);
193 size_t assembled_length = assembled.Length(); 194 if (flow.failed())
195 return false;
194 196
195 output->clear(); 197 output->clear();
196 output->assign(reinterpret_cast<const char*>(assembled_buffer), 198 output->assign(reinterpret_cast<const char*>(sink.Buffer()), sink.Length());
197 assembled_length); 199 return true;
198 result = true;
199 }
200 }
201 }
202
203 return result;
204 } 200 }
205 201
206 TEST_F(DecodeFuzzTest, All) { 202 TEST_F(DecodeFuzzTest, All) {
207 FuzzExe("setup1.exe"); 203 FuzzExe("setup1.exe");
208 FuzzExe("elf-32-1.exe"); 204 FuzzExe("elf-32-1.exe");
209 } 205 }
210 206
211 int main(int argc, char** argv) { 207 int main(int argc, char** argv) {
212 return base::TestSuite(argc, argv).Run(); 208 return base::TestSuite(argc, argv).Run();
213 } 209 }
OLDNEW
« no previous file with comments | « courgette/encode_decode_unittest.cc ('k') | courgette/patch_generator_x86_32.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698