xref: /aosp_15_r20/external/AFLplusplus/instrumentation/compare-transform-pass.so.cc (revision 08b48e0b10e97b33e7b60c5b6e2243bd915777f2)
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