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