1 //===- InjectorIRStrategyTest.cpp - Tests for injector strategy -----------===// 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/ADT/StringRef.h" 10 #include "llvm/AsmParser/Parser.h" 11 #include "llvm/AsmParser/SlotMapping.h" 12 #include "llvm/FuzzMutate/IRMutator.h" 13 #include "llvm/FuzzMutate/Operations.h" 14 #include "llvm/IR/Instructions.h" 15 #include "llvm/IR/LLVMContext.h" 16 #include "llvm/IR/Module.h" 17 #include "llvm/IR/Verifier.h" 18 #include "llvm/Support/SourceMgr.h" 19 20 #include "gtest/gtest.h" 21 22 using namespace llvm; 23 24 static constexpr int Seed = 5; 25 26 namespace { 27 28 std::unique_ptr<IRMutator> createInjectorMutator() { 29 std::vector<TypeGetter> Types{ 30 Type::getInt1Ty, Type::getInt8Ty, Type::getInt16Ty, Type::getInt32Ty, 31 Type::getInt64Ty, Type::getFloatTy, Type::getDoubleTy}; 32 33 std::vector<std::unique_ptr<IRMutationStrategy>> Strategies; 34 Strategies.push_back( 35 std::make_unique<InjectorIRStrategy>( 36 InjectorIRStrategy::getDefaultOps())); 37 38 return std::make_unique<IRMutator>(std::move(Types), std::move(Strategies)); 39 } 40 41 std::unique_ptr<IRMutator> createDeleterMutator() { 42 std::vector<TypeGetter> Types{ 43 Type::getInt1Ty, Type::getInt8Ty, Type::getInt16Ty, Type::getInt32Ty, 44 Type::getInt64Ty, Type::getFloatTy, Type::getDoubleTy}; 45 46 std::vector<std::unique_ptr<IRMutationStrategy>> Strategies; 47 Strategies.push_back(std::make_unique<InstDeleterIRStrategy>()); 48 49 return std::make_unique<IRMutator>(std::move(Types), std::move(Strategies)); 50 } 51 52 std::unique_ptr<IRMutator> createInstModifierMutator() { 53 std::vector<TypeGetter> Types{ 54 Type::getInt1Ty, Type::getInt8Ty, Type::getInt16Ty, Type::getInt32Ty, 55 Type::getInt64Ty, Type::getFloatTy, Type::getDoubleTy}; 56 57 std::vector<std::unique_ptr<IRMutationStrategy>> Strategies; 58 Strategies.push_back(std::make_unique<InstModificationIRStrategy>()); 59 60 return std::make_unique<IRMutator>(std::move(Types), std::move(Strategies)); 61 } 62 63 std::unique_ptr<Module> parseAssembly( 64 const char *Assembly, LLVMContext &Context) { 65 66 SMDiagnostic Error; 67 std::unique_ptr<Module> M = parseAssemblyString(Assembly, Error, Context); 68 69 std::string ErrMsg; 70 raw_string_ostream OS(ErrMsg); 71 Error.print("", OS); 72 73 assert(M && !verifyModule(*M, &errs())); 74 return M; 75 } 76 77 void IterateOnSource(StringRef Source, IRMutator &Mutator) { 78 LLVMContext Ctx; 79 80 for (int i = 0; i < 10; ++i) { 81 auto M = parseAssembly(Source.data(), Ctx); 82 ASSERT_TRUE(M && !verifyModule(*M, &errs())); 83 84 Mutator.mutateModule(*M, Seed, Source.size(), Source.size() + 100); 85 EXPECT_TRUE(!verifyModule(*M, &errs())); 86 } 87 } 88 89 TEST(InjectorIRStrategyTest, EmptyModule) { 90 // Test that we can inject into empty module 91 92 LLVMContext Ctx; 93 auto M = std::make_unique<Module>("M", Ctx); 94 ASSERT_TRUE(M && !verifyModule(*M, &errs())); 95 96 auto Mutator = createInjectorMutator(); 97 ASSERT_TRUE(Mutator); 98 99 Mutator->mutateModule(*M, Seed, 1, 1); 100 EXPECT_TRUE(!verifyModule(*M, &errs())); 101 } 102 103 TEST(InstDeleterIRStrategyTest, EmptyFunction) { 104 // Test that we don't crash even if we can't remove from one of the functions. 105 106 StringRef Source = "" 107 "define <8 x i32> @func1() {\n" 108 "ret <8 x i32> undef\n" 109 "}\n" 110 "\n" 111 "define i32 @func2() {\n" 112 "%A9 = alloca i32\n" 113 "%L6 = load i32, i32* %A9\n" 114 "ret i32 %L6\n" 115 "}\n"; 116 117 auto Mutator = createDeleterMutator(); 118 ASSERT_TRUE(Mutator); 119 120 IterateOnSource(Source, *Mutator); 121 } 122 123 TEST(InstDeleterIRStrategyTest, PhiNodes) { 124 // Test that inst deleter works correctly with the phi nodes. 125 126 LLVMContext Ctx; 127 StringRef Source = "\n\ 128 define i32 @earlyreturncrash(i32 %x) {\n\ 129 entry:\n\ 130 switch i32 %x, label %sw.epilog [\n\ 131 i32 1, label %sw.bb1\n\ 132 ]\n\ 133 \n\ 134 sw.bb1:\n\ 135 br label %sw.epilog\n\ 136 \n\ 137 sw.epilog:\n\ 138 %a.0 = phi i32 [ 7, %entry ], [ 9, %sw.bb1 ]\n\ 139 %b.0 = phi i32 [ 10, %entry ], [ 4, %sw.bb1 ]\n\ 140 ret i32 %a.0\n\ 141 }"; 142 143 auto Mutator = createDeleterMutator(); 144 ASSERT_TRUE(Mutator); 145 146 IterateOnSource(Source, *Mutator); 147 } 148 149 static void checkModifyNoUnsignedAndNoSignedWrap(StringRef Opc) { 150 LLVMContext Ctx; 151 std::string Source = std::string("\n\ 152 define i32 @test(i32 %x) {\n\ 153 %a = ") + Opc.str() + 154 std::string(" i32 %x, 10\n\ 155 ret i32 %a\n\ 156 }"); 157 158 auto Mutator = createInstModifierMutator(); 159 ASSERT_TRUE(Mutator); 160 161 auto M = parseAssembly(Source.data(), Ctx); 162 auto &F = *M->begin(); 163 auto *AddI = &*F.begin()->begin(); 164 ASSERT_TRUE(M && !verifyModule(*M, &errs())); 165 bool FoundNUW = false; 166 bool FoundNSW = false; 167 for (int i = 0; i < 100; ++i) { 168 Mutator->mutateModule(*M, Seed + i, Source.size(), Source.size() + 100); 169 EXPECT_TRUE(!verifyModule(*M, &errs())); 170 FoundNUW |= AddI->hasNoUnsignedWrap(); 171 FoundNSW |= AddI->hasNoSignedWrap(); 172 } 173 174 // The mutator should have added nuw and nsw during some mutations. 175 EXPECT_TRUE(FoundNUW); 176 EXPECT_TRUE(FoundNSW); 177 } 178 TEST(InstModificationIRStrategyTest, Add) { 179 checkModifyNoUnsignedAndNoSignedWrap("add"); 180 } 181 182 TEST(InstModificationIRStrategyTest, Sub) { 183 checkModifyNoUnsignedAndNoSignedWrap("sub"); 184 } 185 186 TEST(InstModificationIRStrategyTest, Mul) { 187 checkModifyNoUnsignedAndNoSignedWrap("mul"); 188 } 189 190 TEST(InstModificationIRStrategyTest, Shl) { 191 checkModifyNoUnsignedAndNoSignedWrap("shl"); 192 } 193 194 TEST(InstModificationIRStrategyTest, ICmp) { 195 LLVMContext Ctx; 196 StringRef Source = "\n\ 197 define i1 @test(i32 %x) {\n\ 198 %a = icmp eq i32 %x, 10\n\ 199 ret i1 %a\n\ 200 }"; 201 202 auto Mutator = createInstModifierMutator(); 203 ASSERT_TRUE(Mutator); 204 205 auto M = parseAssembly(Source.data(), Ctx); 206 auto &F = *M->begin(); 207 CmpInst *CI = cast<CmpInst>(&*F.begin()->begin()); 208 ASSERT_TRUE(M && !verifyModule(*M, &errs())); 209 bool FoundNE = false; 210 for (int i = 0; i < 100; ++i) { 211 Mutator->mutateModule(*M, Seed + i, Source.size(), Source.size() + 100); 212 EXPECT_TRUE(!verifyModule(*M, &errs())); 213 FoundNE |= CI->getPredicate() == CmpInst::ICMP_NE; 214 } 215 216 EXPECT_TRUE(FoundNE); 217 } 218 219 TEST(InstModificationIRStrategyTest, GEP) { 220 LLVMContext Ctx; 221 StringRef Source = "\n\ 222 define i32* @test(i32* %ptr) {\n\ 223 %gep = getelementptr i32, i32* %ptr, i32 10\n\ 224 ret i32* %gep\n\ 225 }"; 226 227 auto Mutator = createInstModifierMutator(); 228 ASSERT_TRUE(Mutator); 229 230 auto M = parseAssembly(Source.data(), Ctx); 231 auto &F = *M->begin(); 232 GetElementPtrInst *GEP = cast<GetElementPtrInst>(&*F.begin()->begin()); 233 ASSERT_TRUE(M && !verifyModule(*M, &errs())); 234 bool FoundInbounds = false; 235 for (int i = 0; i < 100; ++i) { 236 Mutator->mutateModule(*M, Seed + i, Source.size(), Source.size() + 100); 237 EXPECT_TRUE(!verifyModule(*M, &errs())); 238 FoundInbounds |= GEP->isInBounds(); 239 } 240 241 EXPECT_TRUE(FoundInbounds); 242 } 243 } 244