OLD | NEW |
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 |
| 14 #include "base/test/test_suite.h" |
14 | 15 |
15 #include <stddef.h> | 16 #include <stddef.h> |
16 | 17 |
17 #include "base/memory/scoped_ptr.h" | |
18 #include "base/test/test_suite.h" | |
19 #include "courgette/assembly_program.h" | |
20 #include "courgette/base_test_unittest.h" | 18 #include "courgette/base_test_unittest.h" |
21 #include "courgette/courgette.h" | 19 #include "courgette/courgette.h" |
22 #include "courgette/program_detector.h" | |
23 #include "courgette/streams.h" | 20 #include "courgette/streams.h" |
24 | 21 |
25 class DecodeFuzzTest : public BaseTest { | 22 class DecodeFuzzTest : public BaseTest { |
26 public: | 23 public: |
27 void FuzzExe(const char *) const; | 24 void FuzzExe(const char *) const; |
28 | 25 |
29 private: | 26 private: |
30 void FuzzByte(const std::string& buffer, const std::string& output, | 27 void FuzzByte(const std::string& buffer, const std::string& output, |
31 size_t index) const; | 28 size_t index) const; |
32 void FuzzBits(const std::string& buffer, const std::string& output, | 29 void FuzzBits(const std::string& buffer, const std::string& output, |
33 size_t index, int bits_to_flip) const; | 30 size_t index, int bits_to_flip) const; |
34 | 31 |
35 // Returns true if could assemble, false if rejected. | 32 // Returns true if could assemble, false if rejected. |
36 bool TryAssemble(const std::string& buffer, std::string* output) const; | 33 bool TryAssemble(const std::string& buffer, std::string* output) const; |
37 }; | 34 }; |
38 | 35 |
39 // Loads an executable and does fuzz testing in the serialized format. | 36 // Loads an executable and does fuzz testing in the serialized format. |
40 void DecodeFuzzTest::FuzzExe(const char* file_name) const { | 37 void DecodeFuzzTest::FuzzExe(const char* file_name) const { |
41 std::string file1 = FileContents(file_name); | 38 std::string file1 = FileContents(file_name); |
42 | 39 |
43 const void* original_buffer = file1.c_str(); | 40 const void* original_buffer = file1.c_str(); |
44 size_t original_length = file1.length(); | 41 size_t original_length = file1.length(); |
45 | 42 |
46 scoped_ptr<courgette::AssemblyProgram> program; | 43 courgette::AssemblyProgram* program = NULL; |
47 const courgette::Status parse_status = | 44 const courgette::Status parse_status = |
48 courgette::ParseDetectedExecutable(original_buffer, original_length, | 45 courgette::ParseDetectedExecutable(original_buffer, original_length, |
49 &program); | 46 &program); |
50 EXPECT_EQ(courgette::C_OK, parse_status); | 47 EXPECT_EQ(courgette::C_OK, parse_status); |
51 | 48 |
52 scoped_ptr<courgette::EncodedProgram> encoded; | 49 courgette::EncodedProgram* encoded = NULL; |
53 const courgette::Status encode_status = Encode(*program, &encoded); | 50 |
| 51 const courgette::Status encode_status = Encode(program, &encoded); |
54 EXPECT_EQ(courgette::C_OK, encode_status); | 52 EXPECT_EQ(courgette::C_OK, encode_status); |
55 | 53 |
56 program.reset(); | 54 DeleteAssemblyProgram(program); |
57 | 55 |
58 courgette::SinkStreamSet sinks; | 56 courgette::SinkStreamSet sinks; |
59 const courgette::Status write_status = | 57 const courgette::Status write_status = WriteEncodedProgram(encoded, &sinks); |
60 WriteEncodedProgram(encoded.get(), &sinks); | |
61 EXPECT_EQ(courgette::C_OK, write_status); | 58 EXPECT_EQ(courgette::C_OK, write_status); |
62 | 59 |
63 encoded.reset(); | 60 DeleteEncodedProgram(encoded); |
64 | 61 |
65 courgette::SinkStream sink; | 62 courgette::SinkStream sink; |
66 bool can_collect = sinks.CopyTo(&sink); | 63 bool can_collect = sinks.CopyTo(&sink); |
67 EXPECT_TRUE(can_collect); | 64 EXPECT_TRUE(can_collect); |
68 | 65 |
69 size_t length = sink.Length(); | 66 size_t length = sink.Length(); |
70 | 67 |
71 std::string base_buffer(reinterpret_cast<const char*>(sink.Buffer()), length); | 68 std::string base_buffer(reinterpret_cast<const char*>(sink.Buffer()), length); |
72 std::string base_output; | 69 std::string base_output; |
73 bool ok = TryAssemble(base_buffer, &base_output); | 70 bool ok = TryAssemble(base_buffer, &base_output); |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 if (index > 60) { // Beyond the origin addresses ... | 163 if (index > 60) { // Beyond the origin addresses ... |
167 EXPECT_NE(0U, changed_byte_count); // ... we expect some difference. | 164 EXPECT_NE(0U, changed_byte_count); // ... we expect some difference. |
168 } | 165 } |
169 // Currently all changes are smaller than this number: | 166 // Currently all changes are smaller than this number: |
170 EXPECT_GE(45000U, changed_byte_count); | 167 EXPECT_GE(45000U, changed_byte_count); |
171 } | 168 } |
172 } | 169 } |
173 | 170 |
174 bool DecodeFuzzTest::TryAssemble(const std::string& buffer, | 171 bool DecodeFuzzTest::TryAssemble(const std::string& buffer, |
175 std::string* output) const { | 172 std::string* output) const { |
176 scoped_ptr<courgette::EncodedProgram> encoded; | 173 courgette::EncodedProgram *encoded = NULL; |
177 bool result = false; | 174 bool result = false; |
178 | 175 |
179 courgette::SourceStreamSet sources; | 176 courgette::SourceStreamSet sources; |
180 bool can_get_source_streams = sources.Init(buffer.c_str(), buffer.length()); | 177 bool can_get_source_streams = sources.Init(buffer.c_str(), buffer.length()); |
181 if (can_get_source_streams) { | 178 if (can_get_source_streams) { |
182 const courgette::Status read_status = | 179 const courgette::Status read_status = |
183 ReadEncodedProgram(&sources, &encoded); | 180 ReadEncodedProgram(&sources, &encoded); |
184 if (read_status == courgette::C_OK) { | 181 if (read_status == courgette::C_OK) { |
185 courgette::SinkStream assembled; | 182 courgette::SinkStream assembled; |
186 const courgette::Status assemble_status = | 183 const courgette::Status assemble_status = Assemble(encoded, &assembled); |
187 Assemble(encoded.get(), &assembled); | |
188 | 184 |
189 if (assemble_status == courgette::C_OK) { | 185 if (assemble_status == courgette::C_OK) { |
190 const void* assembled_buffer = assembled.Buffer(); | 186 const void* assembled_buffer = assembled.Buffer(); |
191 size_t assembled_length = assembled.Length(); | 187 size_t assembled_length = assembled.Length(); |
192 | 188 |
193 output->clear(); | 189 output->clear(); |
194 output->assign(reinterpret_cast<const char*>(assembled_buffer), | 190 output->assign(reinterpret_cast<const char*>(assembled_buffer), |
195 assembled_length); | 191 assembled_length); |
196 result = true; | 192 result = true; |
197 } | 193 } |
198 } | 194 } |
199 } | 195 } |
200 | 196 |
| 197 DeleteEncodedProgram(encoded); |
| 198 |
201 return result; | 199 return result; |
202 } | 200 } |
203 | 201 |
204 TEST_F(DecodeFuzzTest, All) { | 202 TEST_F(DecodeFuzzTest, All) { |
205 FuzzExe("setup1.exe"); | 203 FuzzExe("setup1.exe"); |
206 FuzzExe("elf-32-1.exe"); | 204 FuzzExe("elf-32-1.exe"); |
207 } | 205 } |
208 | 206 |
209 int main(int argc, char** argv) { | 207 int main(int argc, char** argv) { |
210 return base::TestSuite(argc, argv).Run(); | 208 return base::TestSuite(argc, argv).Run(); |
211 } | 209 } |
OLD | NEW |