1 //===- OperationsTest.cpp - Tests for fuzzer operations -------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/FuzzMutate/Operations.h"
10 #include "llvm/AsmParser/Parser.h"
11 #include "llvm/FuzzMutate/OpDescriptor.h"
12 #include "llvm/IR/Constants.h"
13 #include "llvm/IR/Instructions.h"
14 #include "llvm/IR/Module.h"
15 #include "llvm/IR/Verifier.h"
16 #include "llvm/Support/SourceMgr.h"
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
19 #include <iostream>
20 
21 // Define some pretty printers to help with debugging failures.
22 namespace llvm {
PrintTo(Type * T,::std::ostream * OS)23 void PrintTo(Type *T, ::std::ostream *OS) {
24   raw_os_ostream ROS(*OS);
25   T->print(ROS);
26 }
27 
PrintTo(BasicBlock * BB,::std::ostream * OS)28 void PrintTo(BasicBlock *BB, ::std::ostream *OS) {
29   raw_os_ostream ROS(*OS);
30   ROS << BB << " (" << BB->getName() << ")";
31 }
32 
PrintTo(Value * V,::std::ostream * OS)33 void PrintTo(Value *V, ::std::ostream *OS) {
34   raw_os_ostream ROS(*OS);
35   ROS << V << " (";
36   V->print(ROS);
37   ROS << ")";
38 }
PrintTo(Constant * C,::std::ostream * OS)39 void PrintTo(Constant *C, ::std::ostream *OS) { PrintTo(cast<Value>(C), OS); }
40 
41 } // namespace llvm
42 
43 using namespace llvm;
44 
45 using testing::AllOf;
46 using testing::AnyOf;
47 using testing::ElementsAre;
48 using testing::Eq;
49 using testing::Ge;
50 using testing::Each;
51 using testing::Truly;
52 using testing::NotNull;
53 using testing::PrintToString;
54 using testing::SizeIs;
55 
56 namespace {
parseAssembly(const char * Assembly,LLVMContext & Context)57 std::unique_ptr<Module> parseAssembly(
58     const char *Assembly, LLVMContext &Context) {
59 
60   SMDiagnostic Error;
61   std::unique_ptr<Module> M = parseAssemblyString(Assembly, Error, Context);
62 
63   std::string ErrMsg;
64   raw_string_ostream OS(ErrMsg);
65   Error.print("", OS);
66 
67   assert(M && !verifyModule(*M, &errs()));
68   return M;
69 }
70 
71 MATCHER_P(TypesMatch, V, "has type " + PrintToString(V->getType())) {
72   return arg->getType() == V->getType();
73 }
74 
75 MATCHER_P(HasType, T, "") { return arg->getType() == T; }
76 
TEST(OperationsTest,SourcePreds)77 TEST(OperationsTest, SourcePreds) {
78   using namespace llvm::fuzzerop;
79 
80   LLVMContext Ctx;
81 
82   Constant *i1 = ConstantInt::getFalse(Ctx);
83   Constant *i8 = ConstantInt::get(Type::getInt8Ty(Ctx), 3);
84   Constant *i16 = ConstantInt::get(Type::getInt16Ty(Ctx), 1 << 15);
85   Constant *i32 = ConstantInt::get(Type::getInt32Ty(Ctx), 0);
86   Constant *i64 = ConstantInt::get(Type::getInt64Ty(Ctx),
87                                    std::numeric_limits<uint64_t>::max());
88   Constant *f16 = ConstantFP::getInfinity(Type::getHalfTy(Ctx));
89   Constant *f32 = ConstantFP::get(Type::getFloatTy(Ctx), 0.0);
90   Constant *f64 = ConstantFP::get(Type::getDoubleTy(Ctx), 123.45);
91   Constant *s =
92       ConstantStruct::get(StructType::create(Ctx, "OpaqueStruct"));
93   Constant *a =
94       ConstantArray::get(ArrayType::get(i32->getType(), 2), {i32, i32});
95   Constant *v8i8 = ConstantVector::getSplat({8, false}, i8);
96   Constant *v4f16 = ConstantVector::getSplat({4, false}, f16);
97   Constant *p0i32 =
98       ConstantPointerNull::get(PointerType::get(i32->getType(), 0));
99 
100   auto OnlyI32 = onlyType(i32->getType());
101   EXPECT_TRUE(OnlyI32.matches({}, i32));
102   EXPECT_FALSE(OnlyI32.matches({}, i64));
103   EXPECT_FALSE(OnlyI32.matches({}, p0i32));
104   EXPECT_FALSE(OnlyI32.matches({}, a));
105 
106   EXPECT_THAT(OnlyI32.generate({}, {}),
107               AllOf(SizeIs(Ge(1u)), Each(TypesMatch(i32))));
108 
109   auto AnyType = anyType();
110   EXPECT_TRUE(AnyType.matches({}, i1));
111   EXPECT_TRUE(AnyType.matches({}, f64));
112   EXPECT_TRUE(AnyType.matches({}, s));
113   EXPECT_TRUE(AnyType.matches({}, v8i8));
114   EXPECT_TRUE(AnyType.matches({}, p0i32));
115 
116   EXPECT_THAT(
117       AnyType.generate({}, {i32->getType(), f16->getType(), v8i8->getType()}),
118       Each(AnyOf(TypesMatch(i32), TypesMatch(f16), TypesMatch(v8i8))));
119 
120   auto AnyInt = anyIntType();
121   EXPECT_TRUE(AnyInt.matches({}, i1));
122   EXPECT_TRUE(AnyInt.matches({}, i64));
123   EXPECT_FALSE(AnyInt.matches({}, f32));
124   EXPECT_FALSE(AnyInt.matches({}, v4f16));
125 
126   EXPECT_THAT(
127       AnyInt.generate({}, {i32->getType(), f16->getType(), v8i8->getType()}),
128       AllOf(SizeIs(Ge(1u)), Each(TypesMatch(i32))));
129 
130   auto AnyFP = anyFloatType();
131   EXPECT_TRUE(AnyFP.matches({}, f16));
132   EXPECT_TRUE(AnyFP.matches({}, f32));
133   EXPECT_FALSE(AnyFP.matches({}, i16));
134   EXPECT_FALSE(AnyFP.matches({}, p0i32));
135   EXPECT_FALSE(AnyFP.matches({}, v4f16));
136 
137   EXPECT_THAT(
138       AnyFP.generate({}, {i32->getType(), f16->getType(), v8i8->getType()}),
139       AllOf(SizeIs(Ge(1u)), Each(TypesMatch(f16))));
140 
141   auto AnyPtr = anyPtrType();
142   EXPECT_TRUE(AnyPtr.matches({}, p0i32));
143   EXPECT_FALSE(AnyPtr.matches({}, i8));
144   EXPECT_FALSE(AnyPtr.matches({}, a));
145   EXPECT_FALSE(AnyPtr.matches({}, v8i8));
146 
147   auto isPointer = [](Value *V) { return V->getType()->isPointerTy(); };
148   EXPECT_THAT(
149       AnyPtr.generate({}, {i32->getType(), f16->getType(), v8i8->getType()}),
150       AllOf(SizeIs(Ge(3u)), Each(Truly(isPointer))));
151 
152   auto AnyVec = anyVectorType();
153   EXPECT_TRUE(AnyVec.matches({}, v8i8));
154   EXPECT_TRUE(AnyVec.matches({}, v4f16));
155   EXPECT_FALSE(AnyVec.matches({}, i8));
156   EXPECT_FALSE(AnyVec.matches({}, a));
157   EXPECT_FALSE(AnyVec.matches({}, s));
158 
159   EXPECT_THAT(AnyVec.generate({}, {v8i8->getType()}),
160               ElementsAre(TypesMatch(v8i8)));
161 
162   auto First = matchFirstType();
163   EXPECT_TRUE(First.matches({i8}, i8));
164   EXPECT_TRUE(First.matches({s, a}, s));
165   EXPECT_FALSE(First.matches({f16}, f32));
166   EXPECT_FALSE(First.matches({v4f16, f64}, f64));
167 
168   EXPECT_THAT(First.generate({i8}, {}), Each(TypesMatch(i8)));
169   EXPECT_THAT(First.generate({f16}, {i8->getType()}),
170               Each(TypesMatch(f16)));
171   EXPECT_THAT(First.generate({v8i8, i32}, {}), Each(TypesMatch(v8i8)));
172 }
173 
TEST(OperationsTest,SplitBlock)174 TEST(OperationsTest, SplitBlock) {
175   LLVMContext Ctx;
176 
177   Module M("M", Ctx);
178   Function *F = Function::Create(FunctionType::get(Type::getVoidTy(Ctx), {},
179                                                    /*isVarArg=*/false),
180                                  GlobalValue::ExternalLinkage, "f", &M);
181   auto SBOp = fuzzerop::splitBlockDescriptor(1);
182 
183   // Create a block with only a return and split it on the return.
184   auto *BB = BasicBlock::Create(Ctx, "BB", F);
185   auto *RI = ReturnInst::Create(Ctx, BB);
186   SBOp.BuilderFunc({UndefValue::get(Type::getInt1Ty(Ctx))}, RI);
187 
188   // We should end up with an unconditional branch from BB to BB1, and the
189   // return ends up in BB1.
190   auto *UncondBr = cast<BranchInst>(BB->getTerminator());
191   ASSERT_TRUE(UncondBr->isUnconditional());
192   auto *BB1 = UncondBr->getSuccessor(0);
193   ASSERT_THAT(RI->getParent(), Eq(BB1));
194 
195   // Now add an instruction to BB1 and split on that.
196   auto *AI = new AllocaInst(Type::getInt8Ty(Ctx), 0, "a", RI);
197   Value *Cond = ConstantInt::getFalse(Ctx);
198   SBOp.BuilderFunc({Cond}, AI);
199 
200   // We should end up with a loop back on BB1 and the instruction we split on
201   // moves to BB2.
202   auto *CondBr = cast<BranchInst>(BB1->getTerminator());
203   EXPECT_THAT(CondBr->getCondition(), Eq(Cond));
204   ASSERT_THAT(CondBr->getNumSuccessors(), Eq(2u));
205   ASSERT_THAT(CondBr->getSuccessor(0), Eq(BB1));
206   auto *BB2 = CondBr->getSuccessor(1);
207   EXPECT_THAT(AI->getParent(), Eq(BB2));
208   EXPECT_THAT(RI->getParent(), Eq(BB2));
209 
210   EXPECT_FALSE(verifyModule(M, &errs()));
211 }
212 
TEST(OperationsTest,SplitEHBlock)213 TEST(OperationsTest, SplitEHBlock) {
214   // Check that we will not try to branch back to the landingpad block using
215   // regular branch instruction
216 
217   LLVMContext Ctx;
218   const char *SourceCode =
219       "declare i32* @f()"
220       "declare i32 @personality_function()"
221       "define i32* @test() personality i32 ()* @personality_function {\n"
222       "entry:\n"
223       "  %val = invoke i32* @f()\n"
224       "          to label %normal unwind label %exceptional\n"
225       "normal:\n"
226       "  ret i32* %val\n"
227       "exceptional:\n"
228       "  %landing_pad4 = landingpad token cleanup\n"
229       "  ret i32* undef\n"
230       "}";
231   auto M = parseAssembly(SourceCode, Ctx);
232 
233   // Get the landingpad block
234   BasicBlock &BB = *std::next(M->getFunction("test")->begin(), 2);
235 
236   fuzzerop::OpDescriptor Descr = fuzzerop::splitBlockDescriptor(1);
237 
238   Descr.BuilderFunc({ConstantInt::getTrue(Ctx)},&*BB.getFirstInsertionPt());
239   ASSERT_TRUE(!verifyModule(*M, &errs()));
240 }
241 
TEST(OperationsTest,SplitBlockWithPhis)242 TEST(OperationsTest, SplitBlockWithPhis) {
243   LLVMContext Ctx;
244 
245   Type *Int8Ty = Type::getInt8Ty(Ctx);
246 
247   Module M("M", Ctx);
248   Function *F = Function::Create(FunctionType::get(Type::getVoidTy(Ctx), {},
249                                                    /*isVarArg=*/false),
250                                  GlobalValue::ExternalLinkage, "f", &M);
251   auto SBOp = fuzzerop::splitBlockDescriptor(1);
252 
253   // Create 3 blocks with an if-then branch.
254   auto *BB1 = BasicBlock::Create(Ctx, "BB1", F);
255   auto *BB2 = BasicBlock::Create(Ctx, "BB2", F);
256   auto *BB3 = BasicBlock::Create(Ctx, "BB3", F);
257   BranchInst::Create(BB2, BB3, ConstantInt::getFalse(Ctx), BB1);
258   BranchInst::Create(BB3, BB2);
259 
260   // Set up phi nodes selecting values for the incoming edges.
261   auto *PHI1 = PHINode::Create(Int8Ty, /*NumReservedValues=*/2, "p1", BB3);
262   PHI1->addIncoming(ConstantInt::get(Int8Ty, 0), BB1);
263   PHI1->addIncoming(ConstantInt::get(Int8Ty, 1), BB2);
264   auto *PHI2 = PHINode::Create(Int8Ty, /*NumReservedValues=*/2, "p2", BB3);
265   PHI2->addIncoming(ConstantInt::get(Int8Ty, 1), BB1);
266   PHI2->addIncoming(ConstantInt::get(Int8Ty, 0), BB2);
267   auto *RI = ReturnInst::Create(Ctx, BB3);
268 
269   // Now we split the block with PHI nodes, making sure they're all updated.
270   Value *Cond = ConstantInt::getFalse(Ctx);
271   SBOp.BuilderFunc({Cond}, RI);
272 
273   // Make sure the PHIs are updated with a value for the third incoming edge.
274   EXPECT_THAT(PHI1->getNumIncomingValues(), Eq(3u));
275   EXPECT_THAT(PHI2->getNumIncomingValues(), Eq(3u));
276   EXPECT_FALSE(verifyModule(M, &errs()));
277 }
278 
TEST(OperationsTest,GEP)279 TEST(OperationsTest, GEP) {
280   LLVMContext Ctx;
281 
282   Type *Int8PtrTy = Type::getInt8PtrTy(Ctx);
283   Type *Int32Ty = Type::getInt32Ty(Ctx);
284 
285   Module M("M", Ctx);
286   Function *F = Function::Create(FunctionType::get(Type::getVoidTy(Ctx), {},
287                                                    /*isVarArg=*/false),
288                                  GlobalValue::ExternalLinkage, "f", &M);
289   auto *BB = BasicBlock::Create(Ctx, "BB", F);
290   auto *RI = ReturnInst::Create(Ctx, BB);
291 
292   auto GEPOp = fuzzerop::gepDescriptor(1);
293   EXPECT_TRUE(GEPOp.SourcePreds[0].matches({}, UndefValue::get(Int8PtrTy)));
294   EXPECT_TRUE(GEPOp.SourcePreds[1].matches({UndefValue::get(Int8PtrTy)},
295                                            ConstantInt::get(Int32Ty, 0)));
296 
297   GEPOp.BuilderFunc({UndefValue::get(Int8PtrTy), ConstantInt::get(Int32Ty, 0)},
298                     RI);
299   EXPECT_FALSE(verifyModule(M, &errs()));
300 }
301 
302 
TEST(OperationsTest,GEPPointerOperand)303 TEST(OperationsTest, GEPPointerOperand) {
304   // Check that we only pick sized pointers for the GEP instructions
305 
306   LLVMContext Ctx;
307   const char *SourceCode =
308       "declare void @f()\n"
309       "define void @test() {\n"
310       "  %v = bitcast void ()* @f to i64 (i8 addrspace(4)*)*\n"
311       "  %a = alloca i64, i32 10\n"
312       "  ret void\n"
313       "}";
314   auto M = parseAssembly(SourceCode, Ctx);
315 
316   fuzzerop::OpDescriptor Descr = fuzzerop::gepDescriptor(1);
317 
318   // Get first basic block of the test function
319   Function &F = *M->getFunction("test");
320   BasicBlock &BB = *F.begin();
321 
322   // Don't match %v
323   ASSERT_FALSE(Descr.SourcePreds[0].matches({}, &*BB.begin()));
324 
325   // Match %a
326   ASSERT_TRUE(Descr.SourcePreds[0].matches({}, &*std::next(BB.begin())));
327 }
328 
TEST(OperationsTest,ExtractAndInsertValue)329 TEST(OperationsTest, ExtractAndInsertValue) {
330   LLVMContext Ctx;
331 
332   Type *Int8PtrTy = Type::getInt8PtrTy(Ctx);
333   Type *Int32Ty = Type::getInt32Ty(Ctx);
334   Type *Int64Ty = Type::getInt64Ty(Ctx);
335 
336   Type *StructTy = StructType::create(Ctx, {Int8PtrTy, Int32Ty});
337   Type *OpaqueTy = StructType::create(Ctx, "OpaqueStruct");
338   Type *ZeroSizedArrayTy = ArrayType::get(Int64Ty, 0);
339   Type *ArrayTy = ArrayType::get(Int64Ty, 4);
340   Type *VectorTy = FixedVectorType::get(Int32Ty, 2);
341 
342   auto EVOp = fuzzerop::extractValueDescriptor(1);
343   auto IVOp = fuzzerop::insertValueDescriptor(1);
344 
345   // Sanity check the source preds.
346   Constant *SVal = UndefValue::get(StructTy);
347   Constant *OVal = UndefValue::get(OpaqueTy);
348   Constant *AVal = UndefValue::get(ArrayTy);
349   Constant *ZAVal = UndefValue::get(ZeroSizedArrayTy);
350   Constant *VVal = UndefValue::get(VectorTy);
351 
352   EXPECT_TRUE(EVOp.SourcePreds[0].matches({}, SVal));
353   EXPECT_FALSE(EVOp.SourcePreds[0].matches({}, OVal));
354   EXPECT_TRUE(EVOp.SourcePreds[0].matches({}, AVal));
355   EXPECT_FALSE(EVOp.SourcePreds[0].matches({}, VVal));
356   EXPECT_TRUE(IVOp.SourcePreds[0].matches({}, SVal));
357   EXPECT_FALSE(IVOp.SourcePreds[0].matches({}, OVal));
358   EXPECT_TRUE(IVOp.SourcePreds[0].matches({}, AVal));
359   EXPECT_FALSE(IVOp.SourcePreds[0].matches({}, VVal));
360 
361   // Don't consider zero sized arrays as viable sources
362   EXPECT_FALSE(EVOp.SourcePreds[0].matches({}, ZAVal));
363   EXPECT_FALSE(IVOp.SourcePreds[0].matches({}, ZAVal));
364 
365   // Make sure we're range checking appropriately.
366   EXPECT_TRUE(
367       EVOp.SourcePreds[1].matches({SVal}, ConstantInt::get(Int32Ty, 0)));
368   EXPECT_TRUE(
369       EVOp.SourcePreds[1].matches({SVal}, ConstantInt::get(Int32Ty, 1)));
370   EXPECT_FALSE(
371       EVOp.SourcePreds[1].matches({SVal}, ConstantInt::get(Int32Ty, 2)));
372   EXPECT_FALSE(
373       EVOp.SourcePreds[1].matches({OVal}, ConstantInt::get(Int32Ty, 0)));
374   EXPECT_FALSE(
375       EVOp.SourcePreds[1].matches({OVal}, ConstantInt::get(Int32Ty, 65536)));
376   EXPECT_TRUE(
377       EVOp.SourcePreds[1].matches({AVal}, ConstantInt::get(Int32Ty, 0)));
378   EXPECT_TRUE(
379       EVOp.SourcePreds[1].matches({AVal}, ConstantInt::get(Int32Ty, 3)));
380   EXPECT_FALSE(
381       EVOp.SourcePreds[1].matches({AVal}, ConstantInt::get(Int32Ty, 4)));
382 
383   EXPECT_THAT(
384       EVOp.SourcePreds[1].generate({SVal}, {}),
385       ElementsAre(ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, 1)));
386 
387   // InsertValue should accept any type in the struct, but only in positions
388   // where it makes sense.
389   EXPECT_TRUE(IVOp.SourcePreds[1].matches({SVal}, UndefValue::get(Int8PtrTy)));
390   EXPECT_TRUE(IVOp.SourcePreds[1].matches({SVal}, UndefValue::get(Int32Ty)));
391   EXPECT_FALSE(IVOp.SourcePreds[1].matches({SVal}, UndefValue::get(Int64Ty)));
392   EXPECT_FALSE(IVOp.SourcePreds[2].matches({SVal, UndefValue::get(Int32Ty)},
393                                            ConstantInt::get(Int32Ty, 0)));
394   EXPECT_TRUE(IVOp.SourcePreds[2].matches({SVal, UndefValue::get(Int32Ty)},
395                                           ConstantInt::get(Int32Ty, 1)));
396 
397   EXPECT_THAT(IVOp.SourcePreds[1].generate({SVal}, {}),
398               Each(AnyOf(HasType(Int32Ty), HasType(Int8PtrTy))));
399   EXPECT_THAT(
400       IVOp.SourcePreds[2].generate({SVal, ConstantInt::get(Int32Ty, 0)}, {}),
401       ElementsAre(ConstantInt::get(Int32Ty, 1)));
402 }
403 
404 }
405