1 /* 2 * Copyright 2016 laf-intel 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * https://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <unistd.h> 20 21 #include <list> 22 #include <string> 23 #include <fstream> 24 #include <sys/time.h> 25 #include "llvm/Config/llvm-config.h" 26 27 #include "llvm/ADT/Statistic.h" 28 #include "llvm/IR/IRBuilder.h" 29 #if LLVM_MAJOR >= 11 /* use new pass manager */ 30 #include "llvm/Passes/PassPlugin.h" 31 #include "llvm/Passes/PassBuilder.h" 32 #include "llvm/IR/PassManager.h" 33 #else 34 #include "llvm/IR/LegacyPassManager.h" 35 #include "llvm/Transforms/IPO/PassManagerBuilder.h" 36 #endif 37 #include "llvm/IR/Module.h" 38 #include "llvm/Support/Debug.h" 39 #include "llvm/Support/raw_ostream.h" 40 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 41 #include "llvm/Pass.h" 42 #include "llvm/Analysis/ValueTracking.h" 43 #if LLVM_VERSION_MAJOR >= 14 /* how about stable interfaces? */ 44 #include "llvm/Passes/OptimizationLevel.h" 45 #endif 46 47 #if LLVM_VERSION_MAJOR >= 4 || \ 48 (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4) 49 #include "llvm/IR/Verifier.h" 50 #include "llvm/IR/DebugInfo.h" 51 #else 52 #include "llvm/Analysis/Verifier.h" 53 #include "llvm/DebugInfo.h" 54 #define nullptr 0 55 #endif 56 57 #include <set> 58 #include "afl-llvm-common.h" 59 60 using namespace llvm; 61 62 namespace { 63 64 #if LLVM_MAJOR >= 11 /* use new pass manager */ 65 class CompareTransform : public PassInfoMixin<CompareTransform> { 66 67 public: CompareTransform()68 CompareTransform() { 69 70 #else 71 class CompareTransform : public ModulePass { 72 73 public: 74 static char ID; 75 CompareTransform() : ModulePass(ID) { 76 77 #endif 78 79 initInstrumentList(); 80 81 } 82 83 #if LLVM_MAJOR < 11 84 #if LLVM_VERSION_MAJOR >= 4 85 StringRef getPassName() const override { 86 87 #else 88 const char *getPassName() const override { 89 90 #endif 91 92 return "cmplog transform"; 93 94 } 95 96 #endif 97 98 #if LLVM_MAJOR >= 11 /* use new pass manager */ 99 PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); 100 #else 101 bool runOnModule(Module &M) override; 102 #endif 103 104 private: 105 bool transformCmps(Module &M, const bool processStrcmp, 106 const bool processMemcmp, const bool processStrncmp, 107 const bool processStrcasecmp, 108 const bool processStrncasecmp); 109 110 }; 111 112 } // namespace 113 114 #if LLVM_MAJOR >= 11 /* use new pass manager */ 115 extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK 116 llvmGetPassPluginInfo() { 117 118 return {LLVM_PLUGIN_API_VERSION, "comparetransform", "v0.1", 119 /* lambda to insert our pass into the pass pipeline. */ 120 [](PassBuilder &PB) { 121 122 #if 1 123 #if LLVM_VERSION_MAJOR <= 13 124 using OptimizationLevel = typename PassBuilder::OptimizationLevel; 125 #endif 126 PB.registerOptimizerLastEPCallback( 127 [](ModulePassManager &MPM, OptimizationLevel OL) { 128 129 MPM.addPass(CompareTransform()); 130 131 }); 132 133 /* TODO LTO registration */ 134 #else 135 using PipelineElement = typename PassBuilder::PipelineElement; 136 PB.registerPipelineParsingCallback([](StringRef Name, 137 ModulePassManager &MPM, 138 ArrayRef<PipelineElement>) { 139 140 if (Name == "comparetransform") { 141 142 MPM.addPass(CompareTransform()); 143 return true; 144 145 } else { 146 147 return false; 148 149 } 150 151 }); 152 153 #endif 154 155 }}; 156 157 } 158 159 #else 160 char CompareTransform::ID = 0; 161 #endif 162 163 bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, 164 const bool processMemcmp, 165 const bool processStrncmp, 166 const bool processStrcasecmp, 167 const bool processStrncasecmp) { 168 169 DenseMap<Value *, std::string *> valueMap; 170 std::vector<CallInst *> calls; 171 LLVMContext & C = M.getContext(); 172 IntegerType * Int8Ty = IntegerType::getInt8Ty(C); 173 IntegerType * Int32Ty = IntegerType::getInt32Ty(C); 174 IntegerType * Int64Ty = IntegerType::getInt64Ty(C); 175 176 #if LLVM_VERSION_MAJOR >= 9 177 FunctionCallee tolowerFn; 178 #else 179 Function *tolowerFn; 180 #endif 181 { 182 183 #if LLVM_VERSION_MAJOR >= 9 184 FunctionCallee 185 #else 186 Constant * 187 #endif 188 c = M.getOrInsertFunction("tolower", Int32Ty, Int32Ty 189 #if LLVM_VERSION_MAJOR < 5 190 , 191 NULL 192 #endif 193 ); 194 #if LLVM_VERSION_MAJOR >= 9 195 tolowerFn = c; 196 #else 197 tolowerFn = cast<Function>(c); 198 #endif 199 200 } 201 202 /* iterate over all functions, bbs and instruction and add suitable calls to 203 * strcmp/memcmp/strncmp/strcasecmp/strncasecmp */ 204 for (auto &F : M) { 205 206 if (!isInInstrumentList(&F, MNAME)) continue; 207 208 for (auto &BB : F) { 209 210 for (auto &IN : BB) { 211 212 CallInst *callInst = nullptr; 213 214 if ((callInst = dyn_cast<CallInst>(&IN))) { 215 216 bool isStrcmp = processStrcmp; 217 bool isMemcmp = processMemcmp; 218 bool isStrncmp = processStrncmp; 219 bool isStrcasecmp = processStrcasecmp; 220 bool isStrncasecmp = processStrncasecmp; 221 bool isIntMemcpy = true; 222 223 Function *Callee = callInst->getCalledFunction(); 224 if (!Callee) continue; 225 if (callInst->getCallingConv() != llvm::CallingConv::C) continue; 226 StringRef FuncName = Callee->getName(); 227 isStrcmp &= 228 (!FuncName.compare("strcmp") || !FuncName.compare("xmlStrcmp") || 229 !FuncName.compare("xmlStrEqual") || 230 !FuncName.compare("g_strcmp0") || 231 !FuncName.compare("curl_strequal") || 232 !FuncName.compare("strcsequal")); 233 isMemcmp &= 234 (!FuncName.compare("memcmp") || !FuncName.compare("bcmp") || 235 !FuncName.compare("CRYPTO_memcmp") || 236 !FuncName.compare("OPENSSL_memcmp") || 237 !FuncName.compare("memcmp_const_time") || 238 !FuncName.compare("memcmpct")); 239 isStrncmp &= (!FuncName.compare("strncmp") || 240 !FuncName.compare("xmlStrncmp") || 241 !FuncName.compare("curl_strnequal")); 242 isStrcasecmp &= (!FuncName.compare("strcasecmp") || 243 !FuncName.compare("stricmp") || 244 !FuncName.compare("ap_cstr_casecmp") || 245 !FuncName.compare("OPENSSL_strcasecmp") || 246 !FuncName.compare("xmlStrcasecmp") || 247 !FuncName.compare("g_strcasecmp") || 248 !FuncName.compare("g_ascii_strcasecmp") || 249 !FuncName.compare("Curl_strcasecompare") || 250 !FuncName.compare("Curl_safe_strcasecompare") || 251 !FuncName.compare("cmsstrcasecmp")); 252 isStrncasecmp &= (!FuncName.compare("strncasecmp") || 253 !FuncName.compare("strnicmp") || 254 !FuncName.compare("ap_cstr_casecmpn") || 255 !FuncName.compare("OPENSSL_strncasecmp") || 256 !FuncName.compare("xmlStrncasecmp") || 257 !FuncName.compare("g_ascii_strncasecmp") || 258 !FuncName.compare("Curl_strncasecompare") || 259 !FuncName.compare("g_strncasecmp")); 260 isIntMemcpy &= !FuncName.compare("llvm.memcpy.p0i8.p0i8.i64"); 261 262 if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp && 263 !isStrncasecmp && !isIntMemcpy) 264 continue; 265 266 /* Verify the strcmp/memcmp/strncmp/strcasecmp/strncasecmp function 267 * prototype */ 268 FunctionType *FT = Callee->getFunctionType(); 269 270 isStrcmp &= 271 FT->getNumParams() == 2 && FT->getReturnType()->isIntegerTy(32) && 272 FT->getParamType(0) == FT->getParamType(1) && 273 FT->getParamType(0) == IntegerType::getInt8PtrTy(M.getContext()); 274 isStrcasecmp &= 275 FT->getNumParams() == 2 && FT->getReturnType()->isIntegerTy(32) && 276 FT->getParamType(0) == FT->getParamType(1) && 277 FT->getParamType(0) == IntegerType::getInt8PtrTy(M.getContext()); 278 isMemcmp &= FT->getNumParams() == 3 && 279 FT->getReturnType()->isIntegerTy(32) && 280 FT->getParamType(0)->isPointerTy() && 281 FT->getParamType(1)->isPointerTy() && 282 FT->getParamType(2)->isIntegerTy(); 283 isStrncmp &= FT->getNumParams() == 3 && 284 FT->getReturnType()->isIntegerTy(32) && 285 FT->getParamType(0) == FT->getParamType(1) && 286 FT->getParamType(0) == 287 IntegerType::getInt8PtrTy(M.getContext()) && 288 FT->getParamType(2)->isIntegerTy(); 289 isStrncasecmp &= FT->getNumParams() == 3 && 290 FT->getReturnType()->isIntegerTy(32) && 291 FT->getParamType(0) == FT->getParamType(1) && 292 FT->getParamType(0) == 293 IntegerType::getInt8PtrTy(M.getContext()) && 294 FT->getParamType(2)->isIntegerTy(); 295 296 if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp && 297 !isStrncasecmp && !isIntMemcpy) 298 continue; 299 300 /* is a str{n,}{case,}cmp/memcmp, check if we have 301 * str{case,}cmp(x, "const") or str{case,}cmp("const", x) 302 * strn{case,}cmp(x, "const", ..) or strn{case,}cmp("const", x, ..) 303 * memcmp(x, "const", ..) or memcmp("const", x, ..) */ 304 Value *Str1P = callInst->getArgOperand(0), 305 *Str2P = callInst->getArgOperand(1); 306 StringRef Str1, Str2; 307 bool HasStr1 = getConstantStringInfo(Str1P, Str1); 308 bool HasStr2 = getConstantStringInfo(Str2P, Str2); 309 310 if (isIntMemcpy && HasStr2) { 311 312 valueMap[Str1P] = new std::string(Str2.str()); 313 // fprintf(stderr, "saved %s for %p\n", Str2.str().c_str(), Str1P); 314 continue; 315 316 } 317 318 // not literal? maybe global or local variable 319 if (!(HasStr1 || HasStr2)) { 320 321 auto *Ptr = dyn_cast<ConstantExpr>(Str2P); 322 if (Ptr && Ptr->getOpcode() == Instruction::GetElementPtr) { 323 324 if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) { 325 326 if (Var->hasInitializer()) { 327 328 if (auto *Array = 329 dyn_cast<ConstantDataArray>(Var->getInitializer())) { 330 331 HasStr2 = true; 332 Str2 = Array->getRawDataValues(); 333 valueMap[Str2P] = new std::string(Str2.str()); 334 // fprintf(stderr, "glo2 %s\n", Str2.str().c_str()); 335 336 } 337 338 } 339 340 } 341 342 } 343 344 if (!HasStr2) { 345 346 Ptr = dyn_cast<ConstantExpr>(Str1P); 347 if (Ptr && Ptr->getOpcode() == Instruction::GetElementPtr) { 348 349 if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) { 350 351 if (Var->hasInitializer()) { 352 353 if (auto *Array = dyn_cast<ConstantDataArray>( 354 Var->getInitializer())) { 355 356 HasStr1 = true; 357 Str1 = Array->getRawDataValues(); 358 valueMap[Str1P] = new std::string(Str1.str()); 359 // fprintf(stderr, "glo1 %s\n", Str1.str().c_str()); 360 361 } 362 363 } 364 365 } 366 367 } 368 369 } else if (isIntMemcpy) { 370 371 valueMap[Str1P] = new std::string(Str2.str()); 372 // fprintf(stderr, "saved\n"); 373 374 } 375 376 } 377 378 if (isIntMemcpy) continue; 379 380 if (!(HasStr1 || HasStr2)) { 381 382 // do we have a saved local variable initialization? 383 std::string *val = valueMap[Str1P]; 384 if (val && !val->empty()) { 385 386 Str1 = StringRef(*val); 387 HasStr1 = true; 388 // fprintf(stderr, "loaded1 %s\n", Str1.str().c_str()); 389 390 } else { 391 392 val = valueMap[Str2P]; 393 if (val && !val->empty()) { 394 395 Str2 = StringRef(*val); 396 HasStr2 = true; 397 // fprintf(stderr, "loaded2 %s\n", Str2.str().c_str()); 398 399 } 400 401 } 402 403 } 404 405 /* handle cases of one string is const, one string is variable */ 406 if (!(HasStr1 || HasStr2)) continue; 407 408 if (isMemcmp || isStrncmp || isStrncasecmp) { 409 410 /* check if third operand is a constant integer 411 * strlen("constStr") and sizeof() are treated as constant */ 412 Value * op2 = callInst->getArgOperand(2); 413 ConstantInt *ilen = dyn_cast<ConstantInt>(op2); 414 if (ilen) { 415 416 // if len is zero this is a pointless call but allow real 417 // implementation to worry about that 418 if (ilen->getZExtValue() < 2) { continue; } 419 420 } else if (isMemcmp) { 421 422 // this *may* supply a len greater than the constant string at 423 // runtime so similarly we don't want to have to handle that 424 continue; 425 426 } 427 428 } 429 430 calls.push_back(callInst); 431 432 } 433 434 } 435 436 } 437 438 } 439 440 if (!calls.size()) return false; 441 if (!be_quiet) 442 printf( 443 "Replacing %zu calls to strcmp/memcmp/strncmp/strcasecmp/strncasecmp\n", 444 calls.size()); 445 446 for (auto &callInst : calls) { 447 448 Value *Str1P = callInst->getArgOperand(0), 449 *Str2P = callInst->getArgOperand(1); 450 StringRef Str1, Str2, ConstStr; 451 std::string TmpConstStr; 452 Value * VarStr; 453 bool HasStr1 = getConstantStringInfo(Str1P, Str1); 454 bool HasStr2 = getConstantStringInfo(Str2P, Str2); 455 uint64_t constStrLen, unrollLen, constSizedLen = 0; 456 bool isMemcmp = false; 457 bool isSizedcmp = false; 458 bool isCaseInsensitive = false; 459 bool needs_null = false; 460 Function * Callee = callInst->getCalledFunction(); 461 462 if (Callee) { 463 464 if (!Callee->getName().compare("memcmp") || 465 !Callee->getName().compare("bcmp") || 466 !Callee->getName().compare("CRYPTO_memcmp") || 467 !Callee->getName().compare("OPENSSL_memcmp") || 468 !Callee->getName().compare("memcmp_const_time") || 469 !Callee->getName().compare("memcmpct") || 470 !Callee->getName().compare("llvm.memcpy.p0i8.p0i8.i64")) 471 isMemcmp = true; 472 473 if (isMemcmp || !Callee->getName().compare("strncmp") || 474 !Callee->getName().compare("xmlStrncmp") || 475 !Callee->getName().compare("curl_strnequal") || 476 !Callee->getName().compare("strncasecmp") || 477 !Callee->getName().compare("strnicmp") || 478 !Callee->getName().compare("ap_cstr_casecmpn") || 479 !Callee->getName().compare("OPENSSL_strncasecmp") || 480 !Callee->getName().compare("xmlStrncasecmp") || 481 !Callee->getName().compare("g_ascii_strncasecmp") || 482 !Callee->getName().compare("Curl_strncasecompare") || 483 !Callee->getName().compare("g_strncasecmp")) 484 isSizedcmp = true; 485 486 if (!Callee->getName().compare("strcasecmp") || 487 !Callee->getName().compare("stricmp") || 488 !Callee->getName().compare("ap_cstr_casecmp") || 489 !Callee->getName().compare("OPENSSL_strcasecmp") || 490 !Callee->getName().compare("xmlStrcasecmp") || 491 !Callee->getName().compare("g_strcasecmp") || 492 !Callee->getName().compare("g_ascii_strcasecmp") || 493 !Callee->getName().compare("Curl_strcasecompare") || 494 !Callee->getName().compare("Curl_safe_strcasecompare") || 495 !Callee->getName().compare("cmsstrcasecmp") || 496 !Callee->getName().compare("strncasecmp") || 497 !Callee->getName().compare("strnicmp") || 498 !Callee->getName().compare("ap_cstr_casecmpn") || 499 !Callee->getName().compare("OPENSSL_strncasecmp") || 500 !Callee->getName().compare("xmlStrncasecmp") || 501 !Callee->getName().compare("g_ascii_strncasecmp") || 502 !Callee->getName().compare("Curl_strncasecompare") || 503 !Callee->getName().compare("g_strncasecmp")) 504 isCaseInsensitive = true; 505 506 } 507 508 if (!isSizedcmp) needs_null = true; 509 510 Value *sizedValue = isSizedcmp ? callInst->getArgOperand(2) : NULL; 511 bool isConstSized = sizedValue && isa<ConstantInt>(sizedValue); 512 513 if (!(HasStr1 || HasStr2)) { 514 515 // do we have a saved local or global variable initialization? 516 std::string *val = valueMap[Str1P]; 517 if (val && !val->empty()) { 518 519 Str1 = StringRef(*val); 520 HasStr1 = true; 521 522 } else { 523 524 val = valueMap[Str2P]; 525 if (val && !val->empty()) { 526 527 Str2 = StringRef(*val); 528 // HasStr2 = true; 529 530 } 531 532 } 533 534 } 535 536 if (isConstSized) { 537 538 constSizedLen = dyn_cast<ConstantInt>(sizedValue)->getZExtValue(); 539 540 } 541 542 if (HasStr1) { 543 544 TmpConstStr = Str1.str(); 545 VarStr = Str2P; 546 547 } else { 548 549 TmpConstStr = Str2.str(); 550 VarStr = Str1P; 551 552 } 553 554 if (TmpConstStr.length() < 2 || 555 (TmpConstStr.length() == 2 && TmpConstStr[1] == 0)) { 556 557 continue; 558 559 } 560 561 // the following is in general OK, but strncmp is sometimes used in binary 562 // data structures and this can result in crashes :( so it is commented out 563 564 // add null termination character implicit in c strings 565 if (needs_null && TmpConstStr[TmpConstStr.length() - 1] != 0) { 566 567 TmpConstStr.append("\0", 1); 568 569 } 570 571 // in the unusual case the const str has embedded null 572 // characters, the string comparison functions should terminate 573 // at the first null 574 if (!isMemcmp && TmpConstStr.find('\0') != std::string::npos) { 575 576 TmpConstStr.assign(TmpConstStr, 0, TmpConstStr.find('\0') + 1); 577 578 } 579 580 constStrLen = TmpConstStr.length(); 581 // prefer use of StringRef (in comparison to std::string a StringRef has 582 // built-in runtime bounds checking, which makes debugging easier) 583 ConstStr = StringRef(TmpConstStr); 584 585 if (isConstSized) 586 unrollLen = constSizedLen < constStrLen ? constSizedLen : constStrLen; 587 else 588 unrollLen = constStrLen; 589 590 /* split before the call instruction */ 591 BasicBlock *bb = callInst->getParent(); 592 BasicBlock *end_bb = bb->splitBasicBlock(BasicBlock::iterator(callInst)); 593 594 BasicBlock *next_lenchk_bb = NULL; 595 if (isSizedcmp && !isConstSized) { 596 597 next_lenchk_bb = 598 BasicBlock::Create(C, "len_check", end_bb->getParent(), end_bb); 599 BranchInst::Create(end_bb, next_lenchk_bb); 600 601 } 602 603 BasicBlock *next_cmp_bb = 604 BasicBlock::Create(C, "cmp_added", end_bb->getParent(), end_bb); 605 BranchInst::Create(end_bb, next_cmp_bb); 606 PHINode *PN = PHINode::Create( 607 Int32Ty, (next_lenchk_bb ? 2 : 1) * unrollLen + 1, "cmp_phi"); 608 609 #if LLVM_VERSION_MAJOR >= 8 610 Instruction *term = bb->getTerminator(); 611 #else 612 TerminatorInst *term = bb->getTerminator(); 613 #endif 614 BranchInst::Create(next_lenchk_bb ? next_lenchk_bb : next_cmp_bb, bb); 615 term->eraseFromParent(); 616 617 for (uint64_t i = 0; i < unrollLen; i++) { 618 619 BasicBlock * cur_cmp_bb = next_cmp_bb, *cur_lenchk_bb = next_lenchk_bb; 620 unsigned char c; 621 622 if (cur_lenchk_bb) { 623 624 IRBuilder<> cur_lenchk_IRB(&*(cur_lenchk_bb->getFirstInsertionPt())); 625 Value * icmp = cur_lenchk_IRB.CreateICmpEQ( 626 sizedValue, ConstantInt::get(sizedValue->getType(), i)); 627 cur_lenchk_IRB.CreateCondBr(icmp, end_bb, cur_cmp_bb); 628 cur_lenchk_bb->getTerminator()->eraseFromParent(); 629 630 PN->addIncoming(ConstantInt::get(Int32Ty, 0), cur_lenchk_bb); 631 632 } 633 634 if (isCaseInsensitive) 635 c = (unsigned char)(tolower((int)ConstStr[i]) & 0xff); 636 else 637 c = (unsigned char)ConstStr[i]; 638 639 IRBuilder<> cur_cmp_IRB(&*(cur_cmp_bb->getFirstInsertionPt())); 640 641 Value *v = ConstantInt::get(Int64Ty, i); 642 Value *ele = cur_cmp_IRB.CreateInBoundsGEP( 643 #if LLVM_VERSION_MAJOR >= 14 644 Int8Ty, 645 #endif 646 VarStr, v, "empty"); 647 Value *load = cur_cmp_IRB.CreateLoad( 648 #if LLVM_VERSION_MAJOR >= 14 649 Int8Ty, 650 #endif 651 ele); 652 653 if (isCaseInsensitive) { 654 655 // load >= 'A' && load <= 'Z' ? load | 0x020 : load 656 load = cur_cmp_IRB.CreateZExt(load, Int32Ty); 657 std::vector<Value *> args; 658 args.push_back(load); 659 load = cur_cmp_IRB.CreateCall(tolowerFn, args); 660 load = cur_cmp_IRB.CreateTrunc(load, Int8Ty); 661 662 } 663 664 Value *isub; 665 if (HasStr1) 666 isub = cur_cmp_IRB.CreateSub(ConstantInt::get(Int8Ty, c), load); 667 else 668 isub = cur_cmp_IRB.CreateSub(load, ConstantInt::get(Int8Ty, c)); 669 670 Value *sext = cur_cmp_IRB.CreateSExt(isub, Int32Ty); 671 PN->addIncoming(sext, cur_cmp_bb); 672 673 if (i < unrollLen - 1) { 674 675 if (cur_lenchk_bb) { 676 677 next_lenchk_bb = 678 BasicBlock::Create(C, "len_check", end_bb->getParent(), end_bb); 679 BranchInst::Create(end_bb, next_lenchk_bb); 680 681 } 682 683 next_cmp_bb = 684 BasicBlock::Create(C, "cmp_added", end_bb->getParent(), end_bb); 685 BranchInst::Create(end_bb, next_cmp_bb); 686 687 Value *icmp = 688 cur_cmp_IRB.CreateICmpEQ(isub, ConstantInt::get(Int8Ty, 0)); 689 cur_cmp_IRB.CreateCondBr( 690 icmp, next_lenchk_bb ? next_lenchk_bb : next_cmp_bb, end_bb); 691 cur_cmp_bb->getTerminator()->eraseFromParent(); 692 693 } else { 694 695 // IRB.CreateBr(end_bb); 696 697 } 698 699 // add offset to varstr 700 // create load 701 // create signed isub 702 // create icmp 703 // create jcc 704 // create next_bb 705 706 } 707 708 /* since the call is the first instruction of the bb it is safe to 709 * replace it with a phi instruction */ 710 BasicBlock::iterator ii(callInst); 711 ReplaceInstWithInst(callInst->getParent()->getInstList(), ii, PN); 712 713 } 714 715 return true; 716 717 } 718 719 #if LLVM_MAJOR >= 11 /* use new pass manager */ 720 PreservedAnalyses CompareTransform::run(Module &M, ModuleAnalysisManager &MAM) { 721 722 #else 723 bool CompareTransform::runOnModule(Module &M) { 724 725 #endif 726 727 if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL) 728 printf( 729 "Running compare-transform-pass by laf.intel@gmail.com, extended by " 730 "heiko@hexco.de\n"); 731 else 732 be_quiet = 1; 733 734 #if LLVM_MAJOR >= 11 /* use new pass manager */ 735 auto PA = PreservedAnalyses::all(); 736 #endif 737 738 transformCmps(M, true, true, true, true, true); 739 verifyModule(M); 740 741 #if LLVM_MAJOR >= 11 /* use new pass manager */ 742 /* if (modified) { 743 744 PA.abandon<XX_Manager>(); 745 746 }*/ 747 748 return PA; 749 #else 750 return true; 751 #endif 752 753 } 754 755 #if LLVM_MAJOR < 11 /* use old pass manager */ 756 static void registerCompTransPass(const PassManagerBuilder &, 757 legacy::PassManagerBase &PM) { 758 759 auto p = new CompareTransform(); 760 PM.add(p); 761 762 } 763 764 static RegisterStandardPasses RegisterCompTransPass( 765 PassManagerBuilder::EP_OptimizerLast, registerCompTransPass); 766 767 static RegisterStandardPasses RegisterCompTransPass0( 768 PassManagerBuilder::EP_EnabledOnOptLevel0, registerCompTransPass); 769 770 #if LLVM_VERSION_MAJOR >= 11 771 static RegisterStandardPasses RegisterCompTransPassLTO( 772 PassManagerBuilder::EP_FullLinkTimeOptimizationLast, registerCompTransPass); 773 #endif 774 #endif 775 776