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

Side by Side Diff: unittests/Bitcode/NaClMungeWriteErrorTests.cpp

Issue 1139673004: Harden writer of munged bitcode for fuzzing (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-llvm.git@master
Patch Set: Added more tests. Created 5 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
OLDNEW
(Empty)
1 //===- llvm/unittest/Bitcode/NaClMungeWriteErrorTests.cpp -----------------===//
2 // Tests parser for PNaCl bitcode instructions.
3 //
4 // The LLVM Compiler Infrastructure
5 //
6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10
11 // Tests write errors for munged bitcode.
12
13 #include "llvm/ADT/STLExtras.h"
14 #include "llvm/Bitcode/NaCl/NaClBitcodeMunge.h"
15 #include "llvm/Bitcode/NaCl/NaClBitcodeParser.h"
16 #include "llvm/Bitcode/NaCl/NaClLLVMBitCodes.h"
17
18 #include "gtest/gtest.h"
19
20 using namespace llvm;
21
22 namespace {
23
24 // Test list of bitcode records.
25 static const uint64_t Terminator = 0x5768798008978675LL;
26 const uint64_t BitcodeRecords[] = {
27 1, naclbitc::BLK_CODE_ENTER, naclbitc::MODULE_BLOCK_ID, 2, Terminator,
28 1, naclbitc::BLK_CODE_ENTER, naclbitc::TYPE_BLOCK_ID_NEW, 3, Terminator,
29 3, naclbitc::TYPE_CODE_NUMENTRY, 2, Terminator,
30 3, naclbitc::TYPE_CODE_VOID, Terminator,
31 3, naclbitc::TYPE_CODE_FUNCTION, 0, 0, Terminator,
32 0, naclbitc::BLK_CODE_EXIT, Terminator,
33 3, naclbitc::MODULE_CODE_FUNCTION, 1, 0, 0, 0, Terminator,
34 1, naclbitc::BLK_CODE_ENTER, naclbitc::FUNCTION_BLOCK_ID, 2, Terminator,
35 3, naclbitc::FUNC_CODE_DECLAREBLOCKS, 1, Terminator,
36 3, naclbitc::FUNC_CODE_INST_RET, Terminator,
37 0, naclbitc::BLK_CODE_EXIT, Terminator,
38 0, naclbitc::BLK_CODE_EXIT, Terminator
39 };
40
41 // Expected output when bitcode records are dumped.
42 const char* ExpectedDump =
43 " 0:0|<65532, 80, 69, 88, 69, 1, 0,|Magic Number: 'PEXE' (80, 69, "
44 "88, 69)\n"
45 " | 8, 0, 17, 0, 4, 0, 2, 0, 0, |PNaCl Version: 2\n"
46 " | 0> |\n"
47 " 16:0|1: <65535, 8, 2> |module { // BlockID = 8\n"
48 " 24:0| 1: <65535, 17, 3> | types { // BlockID = 17\n"
49 " 32:0| 3: <1, 2> | count 2;\n"
50 " 34:5| 3: <2> | @t0 = void;\n"
51 " 36:4| 3: <21, 0, 0> | @t1 = void ();\n"
52 " 39:7| 0: <65534> | }\n"
53 " 44:0| 3: <8, 1, 0, 0, 0> | define external void @f0();\n"
54 " 48:6| 1: <65535, 12, 2> | function void @f0() { \n"
55 " | | // BlockID "
56 "= 12\n"
57 " 56:0| 3: <1, 1> | blocks 1;\n"
58 " | | %b0:\n"
59 " 58:4| 3: <10> | ret void;\n"
60 " 60:2| 0: <65534> | }\n"
61 " 64:0|0: <65534> |}\n"
62 ;
63
64 // Edit to change void type with an illegal abbreviation index.
65 const uint64_t VoidTypeIndex = 3; // Index for "@t0 = void".
66 const uint64_t AbbrevIndex4VoidTypeEdit[] = {
67 VoidTypeIndex, NaClMungedBitcode::Replace,
68 4, naclbitc::TYPE_CODE_VOID, Terminator,
69 };
70
71 // Edit to add local abbreviation for "ret void", and then use on that
72 // instruction.
73 const uint64_t RetVoidIndex = 9; // return void;
74 const uint64_t UseLocalRetVoidAbbrevEdits[] = {
75 RetVoidIndex, NaClMungedBitcode::AddBefore,
76 2, naclbitc::BLK_CODE_DEFINE_ABBREV, 1, 1,
77 naclbitc::FUNC_CODE_INST_RET, Terminator,
78 RetVoidIndex, NaClMungedBitcode::Replace,
79 4, naclbitc::FUNC_CODE_INST_RET, Terminator
80 };
81
82 #define ARRAY_ARGS(Records) Records, array_lengthof(Records)
83
84 #define ARRAY_ARGS_TERM(Records) ARRAY_ARGS(Records), Terminator
85
86 std::string stringify(NaClBitcodeMunger &Munger) {
87 std::string Buffer;
88 raw_string_ostream StrBuf(Buffer);
89 Munger.getMungedBitcode().print(StrBuf);
90 return StrBuf.str();
91 }
92
93 // Show that we can dump the bitcode records
94 TEST(NaClMungeWriteErrorTests, DumpBitcodeRecords) {
95 NaClObjDumpMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords));
96 EXPECT_TRUE(Munger.runTest("DumpBitcodeRecords"));
97 EXPECT_EQ(ExpectedDump, Munger.getTestResults());
98 }
99
100 // Show that by default, one can't write a bad abbreviation index.
101 TEST(NaClMungeWriteErrorTests, CantWriteBadAbbrevIndex) {
102 NaClWriteMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords));
103 EXPECT_FALSE(Munger.runTest("CantWriteBadAbbrevIndex",
104 ARRAY_ARGS(AbbrevIndex4VoidTypeEdit)));
105 EXPECT_EQ(
106 "Error (Block 17): Uses illegal abbreviation index: 4: [2]\n"
107 "Error: Unable to generate bitcode file due to write errors\n",
108 Munger.getTestResults());
109 }
110
111 // Show that we can't write more local abbreviations than specified in
112 // the corresponding enclosing block.
113 TEST(NaClMungeWriteErrorTests, CantWriteTooManyLocalAbbreviations) {
114 NaClWriteMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords));
115 Munger.munge(ARRAY_ARGS(UseLocalRetVoidAbbrevEdits));
116 EXPECT_EQ(
117 " 1: [65535, 8, 2]\n"
118 " 1: [65535, 17, 3]\n"
119 " 3: [1, 2]\n"
120 " 3: [2]\n"
121 " 3: [21, 0, 0]\n"
122 " 0: [65534]\n"
123 " 3: [8, 1, 0, 0, 0]\n"
124 " 1: [65535, 12, 2]\n"
125 " 3: [1, 1]\n"
126 " 2: [65533, 1, 1, 10]\n"
127 " 4: [10]\n"
128 " 0: [65534]\n"
129 " 0: [65534]\n",
130 stringify(Munger));
131
132 EXPECT_FALSE(Munger.runTest("CantWriteTooManyLocalAbbreviations"));
133 EXPECT_EQ(
134 "Error (Block 12): Exceeds abbreviation index limit of 3: 2: [65533,"
135 " 1, 1, 10]\n"
136 "Error: Unable to generate bitcode file due to write errors\n",
137 Munger.getTestResults());
138 }
139
140 // Show what happens when there are more enter blocks then exit blocks.
141 TEST(NaClMungeWriteErrorTests, CantWriteTooManyEnterBlocks) {
142 NaClWriteMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords));
143 // Remove all but first two records (i.e. two enter blocks).
144 NaClMungedBitcode &MungedBitcode = Munger.getMungedBitcode();
145 for (size_t i = 2; i < MungedBitcode.getBaseRecords().size(); ++i) {
146 MungedBitcode.remove(i);
147 }
148
149 EXPECT_FALSE(Munger.runTest("TooManyEnterBlocks"));
jvoung (off chromium) 2015/05/13 22:24:06 CantWriteTooManyEnterBlocks -- I wasn't too sure t
Karl 2015/05/14 17:08:12 I agree that these names are no longer useful. Cha
150 EXPECT_EQ(
151 "Error (Block 17): Missing close block.\n"
152 "Error (Block 8): Missing close block.\n"
153 "Error: Unable to generate bitcode file due to write errors\n",
154 Munger.getTestResults());
155 }
156
157 // Show what happens when there are fewer enter blocks than exit
158 // blocks.
159 TEST(NaClMungeWriteErrorTests, CantWriteTooManyExitBlocks) {
160 NaClWriteMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords));
161 // Add two exit blocks.
162 NaClMungedBitcode &MungedBitcode = Munger.getMungedBitcode();
163 NaClRecordVector Values;
164 NaClBitcodeAbbrevRecord Record(0, naclbitc::BLK_CODE_EXIT, Values);
165 for (size_t i = 0; i < 2; ++i)
166 MungedBitcode.addAfter(MungedBitcode.getBaseRecords().size() - 1, Record);
167
168 EXPECT_FALSE(Munger.runTest("CantWriteTooManyExitBlocks"));
169 EXPECT_EQ(
170 "Error (Block unknown): Extraneous exit block: 0: [65534]\n"
171 "Error: Unable to generate bitcode file due to write errors\n",
172 Munger.getTestResults());
173 }
174
175 // Show that an error occurs when writing a bitcode record that isn't
176 // in any block.
177 TEST(NaClMungeWriteErrorTests, CantWriteRecordOutsideBlock) {
178 NaClWriteMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords));
179 NaClMungedBitcode &MungedBitcode = Munger.getMungedBitcode();
180 NaClRecordVector Values;
181 Values.push_back(4);
182 NaClBitcodeAbbrevRecord Record(naclbitc::UNABBREV_RECORD,
183 naclbitc::MODULE_CODE_VERSION,
184 Values);
185
186 MungedBitcode.addAfter(MungedBitcode.getBaseRecords().size() - 1, Record);
187 EXPECT_FALSE(Munger.runTest("CantWriteRecordOutsideBlock"));
188 EXPECT_EQ(
189 "Error (Block unknown): Record outside block: 3: [1, 4]\n"
190 "Error: Unable to generate bitcode file due to write errors\n",
191 Munger.getTestResults());
192 }
193
194 // Show that no error occurs if we write out the maximum allowable
195 // block abbreviation index bit limit.
196 TEST(NaClMungerWriteErrorTests, CantWriteBlockWithMaxLimit) {
Karl 2015/05/13 21:39:25 Added this test.
jvoung (off chromium) 2015/05/13 22:24:06 Seems like Cant should be Can, since this doesn't
Karl 2015/05/14 17:08:12 Good point. Fixing name.
197 // Replace initial block enter with maximum bit size.
198 const uint64_t Edit[] = {
199 0, NaClMungedBitcode::Replace,
200 1, naclbitc::BLK_CODE_ENTER, naclbitc::MODULE_BLOCK_ID,
201 naclbitc::MaxAbbrevWidth, Terminator
202 };
203 NaClWriteMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords));
204 EXPECT_TRUE(Munger.runTest("CantWriteBlockWithMaxLimit", ARRAY_ARGS(Edit)));
205 EXPECT_EQ(
206 " 1: [65535, 8, 32]\n"
207 " 1: [65535, 17, 3]\n"
208 " 3: [1, 2]\n"
209 " 3: [2]\n"
210 " 3: [21, 0, 0]\n"
211 " 0: [65534]\n"
212 " 3: [8, 1, 0, 0, 0]\n"
213 " 1: [65535, 12, 2]\n"
214 " 3: [1, 1]\n"
215 " 3: [10]\n"
216 " 0: [65534]\n"
217 " 0: [65534]\n",
218 Munger.getTestResults());
219 }
220
221 // Show that an error occurs if the block abbreviation index bit limit is
222 // greater than the maximum allowable.
223 TEST(NaClMungerWriteErrorTests, CantWriteBlockWithBadBitLimit) {
Karl 2015/05/13 21:39:25 Added this test.
224 // Replace initial block enter with value out of range.
225 const uint64_t Edit[] = {
226 0, NaClMungedBitcode::Replace,
227 1, naclbitc::BLK_CODE_ENTER, naclbitc::MODULE_BLOCK_ID,
228 naclbitc::MaxAbbrevWidth + 1, Terminator
229 };
230 NaClWriteMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords));
231 EXPECT_FALSE(Munger.runTest("CantWriteBlockWithBadBitLimit",
232 ARRAY_ARGS(Edit)));
233 EXPECT_EQ(
234 "Error (Block unknown): Block index bit limit 33 invalid. Must be in"
235 " [2..32]: 1: [65535, 8, 33]\n"
236 "Error: Unable to generate bitcode file due to write errors\n",
237 Munger.getTestResults());
238 }
239
240 // Show that we can't write an enter block with a very large block id.
241 TEST(NaClMungerWriteErrorTests, CantWriteBlockWithLargeBlockID) {
Karl 2015/05/13 21:39:25 Added this test.
242 // Replace initial block enter with value out of range.
243 const uint64_t Edit[] = {
244 0, NaClMungedBitcode::Replace,
245 1, naclbitc::BLK_CODE_ENTER, (uint64_t)1 << 33, 2, Terminator
246 };
247 NaClWriteMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords));
248 EXPECT_FALSE(Munger.runTest("CantWriteBlockWithLargeBlockID",
249 ARRAY_ARGS(Edit)));
250 EXPECT_EQ(
251 "Error (Block unknown): Block id must be less than << 4294967295: 1:"
jvoung (off chromium) 2015/05/13 22:24:06 "less than << 4294967295" -- why the "<<" ?
Karl 2015/05/14 17:08:11 Done.
252 " [65535, 8589934592, 2]\n"
253 "Error: Unable to generate bitcode file due to write errors\n",
254 Munger.getTestResults());
255 }
256
257 // Show that parsing successfully recovers (i.e. not crash) if the
jvoung (off chromium) 2015/05/13 22:24:06 "parsing successfully recovers" ? I thought it was
Karl 2015/05/14 17:08:11 Good point. Rewrote to better fit test.
258 // bitcode has a bad abbreviation index. Show this by forcing
259 // the bad abbreviation index into the bitcode.
260 TEST(MyNaClMungerWriteErrorTests, DieOnWriteBadAbbreviationIndex) {
Karl 2015/05/13 21:39:25 Added this test.
jvoung (off chromium) 2015/05/13 22:24:06 My... -> NaClMungerWriteErrorTests
261 NaClWriteMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords));
262 Munger.setWriteBadAbbrevIndex(true);
263 Munger.setRunAsDeathTest(true);
264 EXPECT_DEATH(
265 Munger.runTest("DieOnWriteBadAbbrevIndex",
266 ARRAY_ARGS(AbbrevIndex4VoidTypeEdit)),
267 ".*"
268 // Report problem while writing.
269 "Error \\(Block 17\\)\\: Uses illegal abbreviation index\\: 4\\: \\[2\\]"
270 ".*"
271 // Corresponding error while parsing.
272 "Fatal\\(35\\:0)\\: Invalid abbreviation \\# 4 defined for record"
273 ".*"
274 // Output of report_fatal_error.
275 "LLVM ERROR\\: Unable to continue"
276 ".*");
277 }
278
279 // Show that error recovery works when writing an illegal abbreviation
280 // index. Show success by parsing fixed bitcode.
281 TEST(NaClMungeWriteErrorTests, RecoverWhenParsingBadAbbrevIndex) {
282 NaClParseBitcodeMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords));
283 Munger.setTryToRecoverOnWrite(true);
284 EXPECT_TRUE(
285 Munger.runTest("RecoverWhenParsingBadAbbrevIndex",
286 ARRAY_ARGS(AbbrevIndex4VoidTypeEdit), true));
287 EXPECT_EQ(
288 "Error (Block 17): Uses illegal abbreviation index: 4: [2]\n"
289 "Successful parse!\n",
290 Munger.getTestResults());
291 }
292
293 // Show that error recovery works when writing an illegal abbreviation
294 // index. Show success by Dumping fixed bitcode.
295 TEST(NaClMungeWriteErrorTests, RecoverWhenParsingBadAbbreviationIndex) {
296 NaClObjDumpMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords));
297 Munger.setTryToRecoverOnWrite(true);
298 EXPECT_TRUE(Munger.runTest("RecoverWhenParsingBadAbbreviationIndex",
299 ARRAY_ARGS(AbbrevIndex4VoidTypeEdit)));
300 std::string Results(
301 "Error (Block 17): Uses illegal abbreviation index: 4: [2]\n");
302 Results.append(ExpectedDump);
303 EXPECT_EQ(Results, Munger.getTestResults());
304 }
305
306 // Show that error recovery works when writing too many locally
307 // defined abbreviations for the corresponding number of bits defined
308 // in the corresponding enter block. Show success by dumping the fixed
309 // bitcode.
310 TEST(NaClMungeWriteErrorTests, RecoverTooManyLocalAbbreviations) {
311 NaClObjDumpMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords));
312 Munger.setTryToRecoverOnWrite(true);
313 Munger.munge(ARRAY_ARGS(UseLocalRetVoidAbbrevEdits));
314
315 EXPECT_TRUE(Munger.runTest("RecoverTooManyLocalAbbreviations"));
316 std::string Results(
317 "Error (Block 12): Exceeds abbreviation index limit of 3: 2:"
318 " [65533, 1, 1, 10]\n"
319 "Error (Block 12): Uses illegal abbreviation index: 4: [10]\n");
320 Results.append(ExpectedDump);
321 EXPECT_EQ(
322 Results,
323 Munger.getTestResults());
324 }
325
326 // Show that error recovery works when writing and there are more
327 // enter blocks than exit blocks. Show success by dumping fixed
328 // bitcode.
329 TEST(NaClMungeWriteErrorTests, RecoverTooManyEnterBlocks) {
330 NaClObjDumpMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords));
331 // Remove all but first two records (i.e. two enter blocks).
332 NaClMungedBitcode &MungedBitcode = Munger.getMungedBitcode();
333 for (size_t i = 2; i < MungedBitcode.getBaseRecords().size(); ++i) {
334 MungedBitcode.remove(i);
335 }
336
337 Munger.setTryToRecoverOnWrite(true);
338 EXPECT_TRUE(Munger.runTest("RecoverTooManyEnterBlocks"));
339 EXPECT_EQ(
340 "Error (Block 17): Missing close block.\n"
341 "Error (Block 8): Missing close block.\n"
342 " 0:0|<65532, 80, 69, 88, 69, 1, 0,|Magic Number: 'PEXE' (80, 69,"
343 " 88, 69)\n"
344 " | 8, 0, 17, 0, 4, 0, 2, 0, 0, |PNaCl Version: 2\n"
345 " | 0> |\n"
346 " 16:0|1: <65535, 8, 2> |module { // BlockID = 8\n"
347 " 24:0| 1: <65535, 17, 3> | types { // BlockID = 17\n"
348 " 32:0| 0: <65534> | }\n"
349 " 36:0|0: <65534> |}\n",
350 Munger.getTestResults());
351 }
352
353 // Show that error recovery works when writing and there are fewer
354 // enter blocks than exit blocks. Show success by dumping the fixed
355 // bitcode.
356 TEST(NaClMungeWriteErrorTests, RecoverTooManyExitBlocks) {
357 NaClObjDumpMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords));
358 // Add two exit blocks.
359 NaClMungedBitcode &MungedBitcode = Munger.getMungedBitcode();
360 NaClRecordVector Values;
361 NaClBitcodeAbbrevRecord Record(0, naclbitc::BLK_CODE_EXIT, Values);
362 for (size_t i = 0; i < 2; ++i)
363 MungedBitcode.addAfter(MungedBitcode.getBaseRecords().size() - 1, Record);
364
365 Munger.setTryToRecoverOnWrite(true);
366 EXPECT_TRUE(Munger.runTest("RecoverTooManyExitBlocks"));
367 std::string Results(
368 "Error (Block unknown): Extraneous exit block: 0: [65534]\n"
369 "Error (Block unknown): Extraneous exit block: 0: [65534]\n");
370 Results.append(ExpectedDump);
371 EXPECT_EQ(
372 Results,
373 Munger.getTestResults());
374 }
375
376 // Show that error recovery works when writing a bitcode record that
377 // isn't in any block. Show success by showing fixed bitcode records.
378 TEST(NaClMungeWriteErrorTests, RecoverWriteRecordOutsideBlock) {
379 NaClWriteMunger Munger(ARRAY_ARGS_TERM(BitcodeRecords));
380 NaClMungedBitcode &MungedBitcode = Munger.getMungedBitcode();
381 NaClRecordVector Values;
382 Values.push_back(4);
383 NaClBitcodeAbbrevRecord Record(naclbitc::UNABBREV_RECORD,
384 naclbitc::MODULE_CODE_VERSION,
385 Values);
386 MungedBitcode.addAfter(MungedBitcode.getBaseRecords().size() - 1, Record);
387
388 Munger.setTryToRecoverOnWrite(true);
389 EXPECT_TRUE(Munger.runTest("RecoverWriteRecordOutsideBlock"));
390 EXPECT_EQ(
391 "Error (Block unknown): Record outside block: 3: [1, 4]\n"
392 "Error (Block unknown): Missing close block.\n"
393 " 1: [65535, 8, 2]\n"
394 " 1: [65535, 17, 3]\n"
395 " 3: [1, 2]\n"
396 " 3: [2]\n"
397 " 3: [21, 0, 0]\n"
398 " 0: [65534]\n"
399 " 3: [8, 1, 0, 0, 0]\n"
400 " 1: [65535, 12, 2]\n"
401 " 3: [1, 1]\n"
402 " 3: [10]\n"
403 " 0: [65534]\n"
404 " 0: [65534]\n"
405 " 1: [65535, 4294967295, 3]\n"
406 " 3: [1, 4]\n"
407 " 0: [65534]\n",
408 Munger.getTestResults());
409 }
410
411 } // end of anonymous namespace.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698