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 { 23 void PrintTo(Type *T, ::std::ostream *OS) { 24 raw_os_ostream ROS(*OS); 25 T->print(ROS); 26 } 27 28 void PrintTo(BasicBlock *BB, ::std::ostream *OS) { 29 raw_os_ostream ROS(*OS); 30 ROS << BB << " (" << BB->getName() << ")"; 31 } 32 33 void PrintTo(Value *V, ::std::ostream *OS) { 34 raw_os_ostream ROS(*OS); 35 ROS << V << " ("; 36 V->print(ROS); 37 ROS << ")"; 38 } 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 { 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 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(ElementCount::getFixed(8), i8); 96 Constant *v4f16 = ConstantVector::getSplat(ElementCount::getFixed(4), 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 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 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 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 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 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 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