xref: /aosp_15_r20/external/AFLplusplus/instrumentation/afl-llvm-dict2file.so.cc (revision 08b48e0b10e97b33e7b60c5b6e2243bd915777f2)
1*08b48e0bSAndroid Build Coastguard Worker /*
2*08b48e0bSAndroid Build Coastguard Worker    american fuzzy lop++ - LLVM LTO instrumentation pass
3*08b48e0bSAndroid Build Coastguard Worker    ----------------------------------------------------
4*08b48e0bSAndroid Build Coastguard Worker 
5*08b48e0bSAndroid Build Coastguard Worker    Written by Marc Heuse <[email protected]>
6*08b48e0bSAndroid Build Coastguard Worker 
7*08b48e0bSAndroid Build Coastguard Worker    Copyright 2019-2024 AFLplusplus Project. All rights reserved.
8*08b48e0bSAndroid Build Coastguard Worker 
9*08b48e0bSAndroid Build Coastguard Worker    Licensed under the Apache License, Version 2.0 (the "License");
10*08b48e0bSAndroid Build Coastguard Worker    you may not use this file except in compliance with the License.
11*08b48e0bSAndroid Build Coastguard Worker    You may obtain a copy of the License at:
12*08b48e0bSAndroid Build Coastguard Worker 
13*08b48e0bSAndroid Build Coastguard Worker      https://www.apache.org/licenses/LICENSE-2.0
14*08b48e0bSAndroid Build Coastguard Worker 
15*08b48e0bSAndroid Build Coastguard Worker    This library is plugged into LLVM when invoking clang through afl-clang-lto.
16*08b48e0bSAndroid Build Coastguard Worker 
17*08b48e0bSAndroid Build Coastguard Worker  */
18*08b48e0bSAndroid Build Coastguard Worker 
19*08b48e0bSAndroid Build Coastguard Worker #define AFL_LLVM_PASS
20*08b48e0bSAndroid Build Coastguard Worker 
21*08b48e0bSAndroid Build Coastguard Worker #include "config.h"
22*08b48e0bSAndroid Build Coastguard Worker #include "debug.h"
23*08b48e0bSAndroid Build Coastguard Worker 
24*08b48e0bSAndroid Build Coastguard Worker #include <stdio.h>
25*08b48e0bSAndroid Build Coastguard Worker #include <stdlib.h>
26*08b48e0bSAndroid Build Coastguard Worker #include <unistd.h>
27*08b48e0bSAndroid Build Coastguard Worker #include <string.h>
28*08b48e0bSAndroid Build Coastguard Worker #include <sys/time.h>
29*08b48e0bSAndroid Build Coastguard Worker #include <sys/types.h>
30*08b48e0bSAndroid Build Coastguard Worker #include <sys/stat.h>
31*08b48e0bSAndroid Build Coastguard Worker #include <fcntl.h>
32*08b48e0bSAndroid Build Coastguard Worker #include <ctype.h>
33*08b48e0bSAndroid Build Coastguard Worker 
34*08b48e0bSAndroid Build Coastguard Worker #include <list>
35*08b48e0bSAndroid Build Coastguard Worker #include <string>
36*08b48e0bSAndroid Build Coastguard Worker #include <fstream>
37*08b48e0bSAndroid Build Coastguard Worker #include <set>
38*08b48e0bSAndroid Build Coastguard Worker 
39*08b48e0bSAndroid Build Coastguard Worker #include "llvm/Config/llvm-config.h"
40*08b48e0bSAndroid Build Coastguard Worker #include "llvm/ADT/Statistic.h"
41*08b48e0bSAndroid Build Coastguard Worker #include "llvm/IR/IRBuilder.h"
42*08b48e0bSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
43*08b48e0bSAndroid Build Coastguard Worker   #include "llvm/Passes/PassPlugin.h"
44*08b48e0bSAndroid Build Coastguard Worker   #include "llvm/Passes/PassBuilder.h"
45*08b48e0bSAndroid Build Coastguard Worker   #include "llvm/IR/PassManager.h"
46*08b48e0bSAndroid Build Coastguard Worker #else
47*08b48e0bSAndroid Build Coastguard Worker   #include "llvm/IR/LegacyPassManager.h"
48*08b48e0bSAndroid Build Coastguard Worker #endif
49*08b48e0bSAndroid Build Coastguard Worker #include "llvm/IR/BasicBlock.h"
50*08b48e0bSAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
51*08b48e0bSAndroid Build Coastguard Worker #include "llvm/IR/DebugInfo.h"
52*08b48e0bSAndroid Build Coastguard Worker #include "llvm/IR/CFG.h"
53*08b48e0bSAndroid Build Coastguard Worker #include "llvm/IR/Verifier.h"
54*08b48e0bSAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
55*08b48e0bSAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
56*08b48e0bSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR < 17
57*08b48e0bSAndroid Build Coastguard Worker   #include "llvm/Transforms/IPO/PassManagerBuilder.h"
58*08b48e0bSAndroid Build Coastguard Worker #endif
59*08b48e0bSAndroid Build Coastguard Worker #include "llvm/Transforms/Utils/BasicBlockUtils.h"
60*08b48e0bSAndroid Build Coastguard Worker #include "llvm/Analysis/LoopInfo.h"
61*08b48e0bSAndroid Build Coastguard Worker #include "llvm/Analysis/ValueTracking.h"
62*08b48e0bSAndroid Build Coastguard Worker #include "llvm/Pass.h"
63*08b48e0bSAndroid Build Coastguard Worker #include "llvm/IR/Constants.h"
64*08b48e0bSAndroid Build Coastguard Worker 
65*08b48e0bSAndroid Build Coastguard Worker #include "afl-llvm-common.h"
66*08b48e0bSAndroid Build Coastguard Worker 
67*08b48e0bSAndroid Build Coastguard Worker #ifndef O_DSYNC
68*08b48e0bSAndroid Build Coastguard Worker   #define O_DSYNC O_SYNC
69*08b48e0bSAndroid Build Coastguard Worker #endif
70*08b48e0bSAndroid Build Coastguard Worker 
71*08b48e0bSAndroid Build Coastguard Worker using namespace llvm;
72*08b48e0bSAndroid Build Coastguard Worker 
73*08b48e0bSAndroid Build Coastguard Worker namespace {
74*08b48e0bSAndroid Build Coastguard Worker 
75*08b48e0bSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
76*08b48e0bSAndroid Build Coastguard Worker class AFLdict2filePass : public PassInfoMixin<AFLdict2filePass> {
77*08b48e0bSAndroid Build Coastguard Worker 
78*08b48e0bSAndroid Build Coastguard Worker   std::ofstream of;
79*08b48e0bSAndroid Build Coastguard Worker   void          dict2file(u8 *, u32);
80*08b48e0bSAndroid Build Coastguard Worker 
81*08b48e0bSAndroid Build Coastguard Worker  public:
AFLdict2filePass()82*08b48e0bSAndroid Build Coastguard Worker   AFLdict2filePass() {
83*08b48e0bSAndroid Build Coastguard Worker 
84*08b48e0bSAndroid Build Coastguard Worker #else
85*08b48e0bSAndroid Build Coastguard Worker 
86*08b48e0bSAndroid Build Coastguard Worker class AFLdict2filePass : public ModulePass {
87*08b48e0bSAndroid Build Coastguard Worker 
88*08b48e0bSAndroid Build Coastguard Worker   std::ofstream of;
89*08b48e0bSAndroid Build Coastguard Worker   void          dict2file(u8 *, u32);
90*08b48e0bSAndroid Build Coastguard Worker 
91*08b48e0bSAndroid Build Coastguard Worker  public:
92*08b48e0bSAndroid Build Coastguard Worker   static char ID;
93*08b48e0bSAndroid Build Coastguard Worker 
94*08b48e0bSAndroid Build Coastguard Worker   AFLdict2filePass() : ModulePass(ID) {
95*08b48e0bSAndroid Build Coastguard Worker 
96*08b48e0bSAndroid Build Coastguard Worker #endif
97*08b48e0bSAndroid Build Coastguard Worker 
98*08b48e0bSAndroid Build Coastguard Worker     if (getenv("AFL_DEBUG")) debug = 1;
99*08b48e0bSAndroid Build Coastguard Worker 
100*08b48e0bSAndroid Build Coastguard Worker   }
101*08b48e0bSAndroid Build Coastguard Worker 
102*08b48e0bSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
103*08b48e0bSAndroid Build Coastguard Worker   PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
104*08b48e0bSAndroid Build Coastguard Worker #else
105*08b48e0bSAndroid Build Coastguard Worker   bool runOnModule(Module &M) override;
106*08b48e0bSAndroid Build Coastguard Worker #endif
107*08b48e0bSAndroid Build Coastguard Worker 
108*08b48e0bSAndroid Build Coastguard Worker };
109*08b48e0bSAndroid Build Coastguard Worker 
110*08b48e0bSAndroid Build Coastguard Worker }  // namespace
111*08b48e0bSAndroid Build Coastguard Worker 
112*08b48e0bSAndroid Build Coastguard Worker #if LLVM_MAJOR >= 11
113*08b48e0bSAndroid Build Coastguard Worker extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK
llvmGetPassPluginInfo()114*08b48e0bSAndroid Build Coastguard Worker llvmGetPassPluginInfo() {
115*08b48e0bSAndroid Build Coastguard Worker 
116*08b48e0bSAndroid Build Coastguard Worker   return {LLVM_PLUGIN_API_VERSION, "AFLdict2filePass", "v0.1",
117*08b48e0bSAndroid Build Coastguard Worker           /* lambda to insert our pass into the pass pipeline. */
118*08b48e0bSAndroid Build Coastguard Worker           [](PassBuilder &PB) {
119*08b48e0bSAndroid Build Coastguard Worker 
120*08b48e0bSAndroid Build Coastguard Worker   #if LLVM_VERSION_MAJOR <= 13
121*08b48e0bSAndroid Build Coastguard Worker             using OptimizationLevel = typename PassBuilder::OptimizationLevel;
122*08b48e0bSAndroid Build Coastguard Worker   #endif
123*08b48e0bSAndroid Build Coastguard Worker             PB.registerOptimizerLastEPCallback(
124*08b48e0bSAndroid Build Coastguard Worker                 [](ModulePassManager &MPM, OptimizationLevel OL) {
125*08b48e0bSAndroid Build Coastguard Worker 
126*08b48e0bSAndroid Build Coastguard Worker                   MPM.addPass(AFLdict2filePass());
127*08b48e0bSAndroid Build Coastguard Worker 
128*08b48e0bSAndroid Build Coastguard Worker                 });
129*08b48e0bSAndroid Build Coastguard Worker 
130*08b48e0bSAndroid Build Coastguard Worker           }};
131*08b48e0bSAndroid Build Coastguard Worker 
132*08b48e0bSAndroid Build Coastguard Worker }
133*08b48e0bSAndroid Build Coastguard Worker 
134*08b48e0bSAndroid Build Coastguard Worker #else
135*08b48e0bSAndroid Build Coastguard Worker char AFLdict2filePass::ID = 0;
136*08b48e0bSAndroid Build Coastguard Worker #endif
137*08b48e0bSAndroid Build Coastguard Worker 
dict2file(u8 * mem,u32 len)138*08b48e0bSAndroid Build Coastguard Worker void AFLdict2filePass::dict2file(u8 *mem, u32 len) {
139*08b48e0bSAndroid Build Coastguard Worker 
140*08b48e0bSAndroid Build Coastguard Worker   u32  i, j, binary = 0;
141*08b48e0bSAndroid Build Coastguard Worker   char line[MAX_AUTO_EXTRA * 8], tmp[8];
142*08b48e0bSAndroid Build Coastguard Worker 
143*08b48e0bSAndroid Build Coastguard Worker   strcpy(line, "\"");
144*08b48e0bSAndroid Build Coastguard Worker   j = 1;
145*08b48e0bSAndroid Build Coastguard Worker   for (i = 0; i < len; i++) {
146*08b48e0bSAndroid Build Coastguard Worker 
147*08b48e0bSAndroid Build Coastguard Worker     if (isprint(mem[i]) && mem[i] != '\\' && mem[i] != '"') {
148*08b48e0bSAndroid Build Coastguard Worker 
149*08b48e0bSAndroid Build Coastguard Worker       line[j++] = mem[i];
150*08b48e0bSAndroid Build Coastguard Worker 
151*08b48e0bSAndroid Build Coastguard Worker     } else {
152*08b48e0bSAndroid Build Coastguard Worker 
153*08b48e0bSAndroid Build Coastguard Worker       if (i + 1 != len || mem[i] != 0 || binary || len == 4 || len == 8) {
154*08b48e0bSAndroid Build Coastguard Worker 
155*08b48e0bSAndroid Build Coastguard Worker         line[j] = 0;
156*08b48e0bSAndroid Build Coastguard Worker         sprintf(tmp, "\\x%02x", (u8)mem[i]);
157*08b48e0bSAndroid Build Coastguard Worker         strcat(line, tmp);
158*08b48e0bSAndroid Build Coastguard Worker         j = strlen(line);
159*08b48e0bSAndroid Build Coastguard Worker 
160*08b48e0bSAndroid Build Coastguard Worker       }
161*08b48e0bSAndroid Build Coastguard Worker 
162*08b48e0bSAndroid Build Coastguard Worker       binary = 1;
163*08b48e0bSAndroid Build Coastguard Worker 
164*08b48e0bSAndroid Build Coastguard Worker     }
165*08b48e0bSAndroid Build Coastguard Worker 
166*08b48e0bSAndroid Build Coastguard Worker   }
167*08b48e0bSAndroid Build Coastguard Worker 
168*08b48e0bSAndroid Build Coastguard Worker   line[j] = 0;
169*08b48e0bSAndroid Build Coastguard Worker   strcat(line, "\"\n");
170*08b48e0bSAndroid Build Coastguard Worker   of << line;
171*08b48e0bSAndroid Build Coastguard Worker   of.flush();
172*08b48e0bSAndroid Build Coastguard Worker 
173*08b48e0bSAndroid Build Coastguard Worker   if (!be_quiet) fprintf(stderr, "Found dictionary token: %s", line);
174*08b48e0bSAndroid Build Coastguard Worker 
175*08b48e0bSAndroid Build Coastguard Worker }
176*08b48e0bSAndroid Build Coastguard Worker 
177*08b48e0bSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
run(Module & M,ModuleAnalysisManager & MAM)178*08b48e0bSAndroid Build Coastguard Worker PreservedAnalyses AFLdict2filePass::run(Module &M, ModuleAnalysisManager &MAM) {
179*08b48e0bSAndroid Build Coastguard Worker 
180*08b48e0bSAndroid Build Coastguard Worker #else
181*08b48e0bSAndroid Build Coastguard Worker bool AFLdict2filePass::runOnModule(Module &M) {
182*08b48e0bSAndroid Build Coastguard Worker 
183*08b48e0bSAndroid Build Coastguard Worker #endif
184*08b48e0bSAndroid Build Coastguard Worker 
185*08b48e0bSAndroid Build Coastguard Worker   DenseMap<Value *, std::string *> valueMap;
186*08b48e0bSAndroid Build Coastguard Worker   char                            *ptr;
187*08b48e0bSAndroid Build Coastguard Worker   int                              found = 0, handle_main = 1;
188*08b48e0bSAndroid Build Coastguard Worker 
189*08b48e0bSAndroid Build Coastguard Worker   /* Show a banner */
190*08b48e0bSAndroid Build Coastguard Worker   setvbuf(stdout, NULL, _IONBF, 0);
191*08b48e0bSAndroid Build Coastguard Worker 
192*08b48e0bSAndroid Build Coastguard Worker   if ((isatty(2) && !getenv("AFL_QUIET")) || debug) {
193*08b48e0bSAndroid Build Coastguard Worker 
194*08b48e0bSAndroid Build Coastguard Worker     SAYF(cCYA "afl-llvm-dict2file" VERSION cRST
195*08b48e0bSAndroid Build Coastguard Worker               " by Marc \"vanHauser\" Heuse <[email protected]>\n");
196*08b48e0bSAndroid Build Coastguard Worker 
197*08b48e0bSAndroid Build Coastguard Worker   } else {
198*08b48e0bSAndroid Build Coastguard Worker 
199*08b48e0bSAndroid Build Coastguard Worker     be_quiet = 1;
200*08b48e0bSAndroid Build Coastguard Worker 
201*08b48e0bSAndroid Build Coastguard Worker   }
202*08b48e0bSAndroid Build Coastguard Worker 
203*08b48e0bSAndroid Build Coastguard Worker   if (getenv("AFL_LLVM_DICT2FILE_NO_MAIN")) { handle_main = 0; }
204*08b48e0bSAndroid Build Coastguard Worker 
205*08b48e0bSAndroid Build Coastguard Worker   scanForDangerousFunctions(&M);
206*08b48e0bSAndroid Build Coastguard Worker 
207*08b48e0bSAndroid Build Coastguard Worker   ptr = getenv("AFL_LLVM_DICT2FILE");
208*08b48e0bSAndroid Build Coastguard Worker 
209*08b48e0bSAndroid Build Coastguard Worker   if (!ptr) {
210*08b48e0bSAndroid Build Coastguard Worker 
211*08b48e0bSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
212*08b48e0bSAndroid Build Coastguard Worker     auto PA = PreservedAnalyses::all();
213*08b48e0bSAndroid Build Coastguard Worker     return PA;
214*08b48e0bSAndroid Build Coastguard Worker #else
215*08b48e0bSAndroid Build Coastguard Worker     return true;
216*08b48e0bSAndroid Build Coastguard Worker #endif
217*08b48e0bSAndroid Build Coastguard Worker 
218*08b48e0bSAndroid Build Coastguard Worker   }
219*08b48e0bSAndroid Build Coastguard Worker 
220*08b48e0bSAndroid Build Coastguard Worker   if (*ptr != '/')
221*08b48e0bSAndroid Build Coastguard Worker     FATAL("AFL_LLVM_DICT2FILE is not set to an absolute path: %s", ptr);
222*08b48e0bSAndroid Build Coastguard Worker 
223*08b48e0bSAndroid Build Coastguard Worker   of.open(ptr, std::ofstream::out | std::ofstream::app);
224*08b48e0bSAndroid Build Coastguard Worker   if (!of.is_open()) PFATAL("Could not open/create %s.", ptr);
225*08b48e0bSAndroid Build Coastguard Worker 
226*08b48e0bSAndroid Build Coastguard Worker   /* Instrument all the things! */
227*08b48e0bSAndroid Build Coastguard Worker 
228*08b48e0bSAndroid Build Coastguard Worker   for (auto &F : M) {
229*08b48e0bSAndroid Build Coastguard Worker 
230*08b48e0bSAndroid Build Coastguard Worker     if (!handle_main &&
231*08b48e0bSAndroid Build Coastguard Worker         (!F.getName().compare("main") || !F.getName().compare("_main"))) {
232*08b48e0bSAndroid Build Coastguard Worker 
233*08b48e0bSAndroid Build Coastguard Worker       continue;
234*08b48e0bSAndroid Build Coastguard Worker 
235*08b48e0bSAndroid Build Coastguard Worker     }
236*08b48e0bSAndroid Build Coastguard Worker 
237*08b48e0bSAndroid Build Coastguard Worker     if (isIgnoreFunction(&F)) { continue; }
238*08b48e0bSAndroid Build Coastguard Worker     if (!isInInstrumentList(&F, MNAME) || !F.size()) { continue; }
239*08b48e0bSAndroid Build Coastguard Worker 
240*08b48e0bSAndroid Build Coastguard Worker     /*  Some implementation notes.
241*08b48e0bSAndroid Build Coastguard Worker      *
242*08b48e0bSAndroid Build Coastguard Worker      *  We try to handle 3 cases:
243*08b48e0bSAndroid Build Coastguard Worker      *  - memcmp("foo", arg, 3) <- literal string
244*08b48e0bSAndroid Build Coastguard Worker      *  - static char globalvar[] = "foo";
245*08b48e0bSAndroid Build Coastguard Worker      *    memcmp(globalvar, arg, 3) <- global variable
246*08b48e0bSAndroid Build Coastguard Worker      *  - char localvar[] = "foo";
247*08b48e0bSAndroid Build Coastguard Worker      *    memcmp(locallvar, arg, 3) <- local variable
248*08b48e0bSAndroid Build Coastguard Worker      *
249*08b48e0bSAndroid Build Coastguard Worker      *  The local variable case is the hardest. We can only detect that
250*08b48e0bSAndroid Build Coastguard Worker      *  case if there is no reassignment or change in the variable.
251*08b48e0bSAndroid Build Coastguard Worker      *  And it might not work across llvm version.
252*08b48e0bSAndroid Build Coastguard Worker      *  What we do is hooking the initializer function for local variables
253*08b48e0bSAndroid Build Coastguard Worker      *  (llvm.memcpy.p0i8.p0i8.i64) and note the string and the assigned
254*08b48e0bSAndroid Build Coastguard Worker      *  variable. And if that variable is then used in a compare function
255*08b48e0bSAndroid Build Coastguard Worker      *  we use that noted string.
256*08b48e0bSAndroid Build Coastguard Worker      *  This seems not to work for tokens that have a size <= 4 :-(
257*08b48e0bSAndroid Build Coastguard Worker      *
258*08b48e0bSAndroid Build Coastguard Worker      *  - if the compared length is smaller than the string length we
259*08b48e0bSAndroid Build Coastguard Worker      *    save the full string. This is likely better for fuzzing but
260*08b48e0bSAndroid Build Coastguard Worker      *    might be wrong in a few cases depending on optimizers
261*08b48e0bSAndroid Build Coastguard Worker      *
262*08b48e0bSAndroid Build Coastguard Worker      *  - not using StringRef because there is a bug in the llvm 11
263*08b48e0bSAndroid Build Coastguard Worker      *    checkout I am using which sometimes points to wrong strings
264*08b48e0bSAndroid Build Coastguard Worker      *
265*08b48e0bSAndroid Build Coastguard Worker      *  Over and out. Took me a full day. damn. mh/vh
266*08b48e0bSAndroid Build Coastguard Worker      */
267*08b48e0bSAndroid Build Coastguard Worker 
268*08b48e0bSAndroid Build Coastguard Worker     for (auto &BB : F) {
269*08b48e0bSAndroid Build Coastguard Worker 
270*08b48e0bSAndroid Build Coastguard Worker       for (auto &IN : BB) {
271*08b48e0bSAndroid Build Coastguard Worker 
272*08b48e0bSAndroid Build Coastguard Worker         CallInst *callInst = nullptr;
273*08b48e0bSAndroid Build Coastguard Worker         CmpInst  *cmpInst = nullptr;
274*08b48e0bSAndroid Build Coastguard Worker 
275*08b48e0bSAndroid Build Coastguard Worker         if ((cmpInst = dyn_cast<CmpInst>(&IN))) {
276*08b48e0bSAndroid Build Coastguard Worker 
277*08b48e0bSAndroid Build Coastguard Worker           Value       *op = cmpInst->getOperand(1);
278*08b48e0bSAndroid Build Coastguard Worker           ConstantInt *ilen = dyn_cast<ConstantInt>(op);
279*08b48e0bSAndroid Build Coastguard Worker 
280*08b48e0bSAndroid Build Coastguard Worker           /* We skip > 64 bit integers. why? first because their value is
281*08b48e0bSAndroid Build Coastguard Worker              difficult to obtain, and second because clang does not support
282*08b48e0bSAndroid Build Coastguard Worker              literals > 64 bit (as of llvm 12) */
283*08b48e0bSAndroid Build Coastguard Worker 
284*08b48e0bSAndroid Build Coastguard Worker           if (ilen && ilen->uge(0xffffffffffffffff) == false) {
285*08b48e0bSAndroid Build Coastguard Worker 
286*08b48e0bSAndroid Build Coastguard Worker             u64 val2 = 0, val = ilen->getZExtValue();
287*08b48e0bSAndroid Build Coastguard Worker             u32 len = 0;
288*08b48e0bSAndroid Build Coastguard Worker             if (val > 0x10000 && val < 0xffffffff) len = 4;
289*08b48e0bSAndroid Build Coastguard Worker             if (val > 0x100000001 && val < 0xffffffffffffffff) len = 8;
290*08b48e0bSAndroid Build Coastguard Worker 
291*08b48e0bSAndroid Build Coastguard Worker             if (len) {
292*08b48e0bSAndroid Build Coastguard Worker 
293*08b48e0bSAndroid Build Coastguard Worker               auto c = cmpInst->getPredicate();
294*08b48e0bSAndroid Build Coastguard Worker 
295*08b48e0bSAndroid Build Coastguard Worker               switch (c) {
296*08b48e0bSAndroid Build Coastguard Worker 
297*08b48e0bSAndroid Build Coastguard Worker                 case CmpInst::FCMP_OGT:  // fall through
298*08b48e0bSAndroid Build Coastguard Worker                 case CmpInst::FCMP_OLE:  // fall through
299*08b48e0bSAndroid Build Coastguard Worker                 case CmpInst::ICMP_SLE:  // fall through
300*08b48e0bSAndroid Build Coastguard Worker                 case CmpInst::ICMP_SGT:
301*08b48e0bSAndroid Build Coastguard Worker 
302*08b48e0bSAndroid Build Coastguard Worker                   // signed comparison and it is a negative constant
303*08b48e0bSAndroid Build Coastguard Worker                   if ((len == 4 && (val & 80000000)) ||
304*08b48e0bSAndroid Build Coastguard Worker                       (len == 8 && (val & 8000000000000000))) {
305*08b48e0bSAndroid Build Coastguard Worker 
306*08b48e0bSAndroid Build Coastguard Worker                     if ((val & 0xffff) != 1) val2 = val - 1;
307*08b48e0bSAndroid Build Coastguard Worker                     break;
308*08b48e0bSAndroid Build Coastguard Worker 
309*08b48e0bSAndroid Build Coastguard Worker                   }
310*08b48e0bSAndroid Build Coastguard Worker 
311*08b48e0bSAndroid Build Coastguard Worker                   // fall through
312*08b48e0bSAndroid Build Coastguard Worker 
313*08b48e0bSAndroid Build Coastguard Worker                 case CmpInst::FCMP_UGT:  // fall through
314*08b48e0bSAndroid Build Coastguard Worker                 case CmpInst::FCMP_ULE:  // fall through
315*08b48e0bSAndroid Build Coastguard Worker                 case CmpInst::ICMP_UGT:  // fall through
316*08b48e0bSAndroid Build Coastguard Worker                 case CmpInst::ICMP_ULE:
317*08b48e0bSAndroid Build Coastguard Worker                   if ((val & 0xffff) != 0xfffe) val2 = val + 1;
318*08b48e0bSAndroid Build Coastguard Worker                   break;
319*08b48e0bSAndroid Build Coastguard Worker 
320*08b48e0bSAndroid Build Coastguard Worker                 case CmpInst::FCMP_OLT:  // fall through
321*08b48e0bSAndroid Build Coastguard Worker                 case CmpInst::FCMP_OGE:  // fall through
322*08b48e0bSAndroid Build Coastguard Worker                 case CmpInst::ICMP_SLT:  // fall through
323*08b48e0bSAndroid Build Coastguard Worker                 case CmpInst::ICMP_SGE:
324*08b48e0bSAndroid Build Coastguard Worker 
325*08b48e0bSAndroid Build Coastguard Worker                   // signed comparison and it is a negative constant
326*08b48e0bSAndroid Build Coastguard Worker                   if ((len == 4 && (val & 80000000)) ||
327*08b48e0bSAndroid Build Coastguard Worker                       (len == 8 && (val & 8000000000000000))) {
328*08b48e0bSAndroid Build Coastguard Worker 
329*08b48e0bSAndroid Build Coastguard Worker                     if ((val & 0xffff) != 1) val2 = val - 1;
330*08b48e0bSAndroid Build Coastguard Worker                     break;
331*08b48e0bSAndroid Build Coastguard Worker 
332*08b48e0bSAndroid Build Coastguard Worker                   }
333*08b48e0bSAndroid Build Coastguard Worker 
334*08b48e0bSAndroid Build Coastguard Worker                   // fall through
335*08b48e0bSAndroid Build Coastguard Worker 
336*08b48e0bSAndroid Build Coastguard Worker                 case CmpInst::FCMP_ULT:  // fall through
337*08b48e0bSAndroid Build Coastguard Worker                 case CmpInst::FCMP_UGE:  // fall through
338*08b48e0bSAndroid Build Coastguard Worker                 case CmpInst::ICMP_ULT:  // fall through
339*08b48e0bSAndroid Build Coastguard Worker                 case CmpInst::ICMP_UGE:
340*08b48e0bSAndroid Build Coastguard Worker                   if ((val & 0xffff) != 1) val2 = val - 1;
341*08b48e0bSAndroid Build Coastguard Worker                   break;
342*08b48e0bSAndroid Build Coastguard Worker 
343*08b48e0bSAndroid Build Coastguard Worker                 default:
344*08b48e0bSAndroid Build Coastguard Worker                   val2 = 0;
345*08b48e0bSAndroid Build Coastguard Worker 
346*08b48e0bSAndroid Build Coastguard Worker               }
347*08b48e0bSAndroid Build Coastguard Worker 
348*08b48e0bSAndroid Build Coastguard Worker               dict2file((u8 *)&val, len);
349*08b48e0bSAndroid Build Coastguard Worker               found++;
350*08b48e0bSAndroid Build Coastguard Worker               if (val2) {
351*08b48e0bSAndroid Build Coastguard Worker 
352*08b48e0bSAndroid Build Coastguard Worker                 dict2file((u8 *)&val2, len);
353*08b48e0bSAndroid Build Coastguard Worker                 found++;
354*08b48e0bSAndroid Build Coastguard Worker 
355*08b48e0bSAndroid Build Coastguard Worker               }
356*08b48e0bSAndroid Build Coastguard Worker 
357*08b48e0bSAndroid Build Coastguard Worker             }
358*08b48e0bSAndroid Build Coastguard Worker 
359*08b48e0bSAndroid Build Coastguard Worker           }
360*08b48e0bSAndroid Build Coastguard Worker 
361*08b48e0bSAndroid Build Coastguard Worker         }
362*08b48e0bSAndroid Build Coastguard Worker 
363*08b48e0bSAndroid Build Coastguard Worker         if ((callInst = dyn_cast<CallInst>(&IN))) {
364*08b48e0bSAndroid Build Coastguard Worker 
365*08b48e0bSAndroid Build Coastguard Worker           bool   isStrcmp = true;
366*08b48e0bSAndroid Build Coastguard Worker           bool   isMemcmp = true;
367*08b48e0bSAndroid Build Coastguard Worker           bool   isStrncmp = true;
368*08b48e0bSAndroid Build Coastguard Worker           bool   isStrcasecmp = true;
369*08b48e0bSAndroid Build Coastguard Worker           bool   isStrncasecmp = true;
370*08b48e0bSAndroid Build Coastguard Worker           bool   isIntMemcpy = true;
371*08b48e0bSAndroid Build Coastguard Worker           bool   isStdString = true;
372*08b48e0bSAndroid Build Coastguard Worker           bool   isStrstr = true;
373*08b48e0bSAndroid Build Coastguard Worker           size_t optLen = 0;
374*08b48e0bSAndroid Build Coastguard Worker 
375*08b48e0bSAndroid Build Coastguard Worker           Function *Callee = callInst->getCalledFunction();
376*08b48e0bSAndroid Build Coastguard Worker           if (!Callee) continue;
377*08b48e0bSAndroid Build Coastguard Worker           if (callInst->getCallingConv() != llvm::CallingConv::C) continue;
378*08b48e0bSAndroid Build Coastguard Worker           std::string FuncName = Callee->getName().str();
379*08b48e0bSAndroid Build Coastguard Worker           isStrcmp &=
380*08b48e0bSAndroid Build Coastguard Worker               (!FuncName.compare("strcmp") || !FuncName.compare("xmlStrcmp") ||
381*08b48e0bSAndroid Build Coastguard Worker                !FuncName.compare("xmlStrEqual") ||
382*08b48e0bSAndroid Build Coastguard Worker                !FuncName.compare("g_strcmp0") ||
383*08b48e0bSAndroid Build Coastguard Worker                !FuncName.compare("curl_strequal") ||
384*08b48e0bSAndroid Build Coastguard Worker                !FuncName.compare("strcsequal"));
385*08b48e0bSAndroid Build Coastguard Worker           isMemcmp &=
386*08b48e0bSAndroid Build Coastguard Worker               (!FuncName.compare("memcmp") || !FuncName.compare("bcmp") ||
387*08b48e0bSAndroid Build Coastguard Worker                !FuncName.compare("CRYPTO_memcmp") ||
388*08b48e0bSAndroid Build Coastguard Worker                !FuncName.compare("OPENSSL_memcmp") ||
389*08b48e0bSAndroid Build Coastguard Worker                !FuncName.compare("memcmp_const_time") ||
390*08b48e0bSAndroid Build Coastguard Worker                !FuncName.compare("memcmpct"));
391*08b48e0bSAndroid Build Coastguard Worker           isStrncmp &= (!FuncName.compare("strncmp") ||
392*08b48e0bSAndroid Build Coastguard Worker                         !FuncName.compare("xmlStrncmp") ||
393*08b48e0bSAndroid Build Coastguard Worker                         !FuncName.compare("curl_strnequal"));
394*08b48e0bSAndroid Build Coastguard Worker           isStrcasecmp &= (!FuncName.compare("strcasecmp") ||
395*08b48e0bSAndroid Build Coastguard Worker                            !FuncName.compare("stricmp") ||
396*08b48e0bSAndroid Build Coastguard Worker                            !FuncName.compare("ap_cstr_casecmp") ||
397*08b48e0bSAndroid Build Coastguard Worker                            !FuncName.compare("OPENSSL_strcasecmp") ||
398*08b48e0bSAndroid Build Coastguard Worker                            !FuncName.compare("xmlStrcasecmp") ||
399*08b48e0bSAndroid Build Coastguard Worker                            !FuncName.compare("g_strcasecmp") ||
400*08b48e0bSAndroid Build Coastguard Worker                            !FuncName.compare("g_ascii_strcasecmp") ||
401*08b48e0bSAndroid Build Coastguard Worker                            !FuncName.compare("Curl_strcasecompare") ||
402*08b48e0bSAndroid Build Coastguard Worker                            !FuncName.compare("Curl_safe_strcasecompare") ||
403*08b48e0bSAndroid Build Coastguard Worker                            !FuncName.compare("cmsstrcasecmp"));
404*08b48e0bSAndroid Build Coastguard Worker           isStrncasecmp &= (!FuncName.compare("strncasecmp") ||
405*08b48e0bSAndroid Build Coastguard Worker                             !FuncName.compare("strnicmp") ||
406*08b48e0bSAndroid Build Coastguard Worker                             !FuncName.compare("ap_cstr_casecmpn") ||
407*08b48e0bSAndroid Build Coastguard Worker                             !FuncName.compare("OPENSSL_strncasecmp") ||
408*08b48e0bSAndroid Build Coastguard Worker                             !FuncName.compare("xmlStrncasecmp") ||
409*08b48e0bSAndroid Build Coastguard Worker                             !FuncName.compare("g_ascii_strncasecmp") ||
410*08b48e0bSAndroid Build Coastguard Worker                             !FuncName.compare("Curl_strncasecompare") ||
411*08b48e0bSAndroid Build Coastguard Worker                             !FuncName.compare("g_strncasecmp"));
412*08b48e0bSAndroid Build Coastguard Worker           isStrstr &= (!FuncName.compare("strstr") ||
413*08b48e0bSAndroid Build Coastguard Worker                        !FuncName.compare("g_strstr_len") ||
414*08b48e0bSAndroid Build Coastguard Worker                        !FuncName.compare("ap_strcasestr") ||
415*08b48e0bSAndroid Build Coastguard Worker                        !FuncName.compare("xmlStrstr") ||
416*08b48e0bSAndroid Build Coastguard Worker                        !FuncName.compare("xmlStrcasestr") ||
417*08b48e0bSAndroid Build Coastguard Worker                        !FuncName.compare("g_str_has_prefix") ||
418*08b48e0bSAndroid Build Coastguard Worker                        !FuncName.compare("g_str_has_suffix"));
419*08b48e0bSAndroid Build Coastguard Worker           isIntMemcpy &= !FuncName.compare("llvm.memcpy.p0i8.p0i8.i64");
420*08b48e0bSAndroid Build Coastguard Worker           isStdString &= ((FuncName.find("basic_string") != std::string::npos &&
421*08b48e0bSAndroid Build Coastguard Worker                            FuncName.find("compare") != std::string::npos) ||
422*08b48e0bSAndroid Build Coastguard Worker                           (FuncName.find("basic_string") != std::string::npos &&
423*08b48e0bSAndroid Build Coastguard Worker                            FuncName.find("find") != std::string::npos));
424*08b48e0bSAndroid Build Coastguard Worker 
425*08b48e0bSAndroid Build Coastguard Worker           if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp &&
426*08b48e0bSAndroid Build Coastguard Worker               !isStrncasecmp && !isIntMemcpy && !isStdString && !isStrstr)
427*08b48e0bSAndroid Build Coastguard Worker             continue;
428*08b48e0bSAndroid Build Coastguard Worker 
429*08b48e0bSAndroid Build Coastguard Worker           /* Verify the strcmp/memcmp/strncmp/strcasecmp/strncasecmp function
430*08b48e0bSAndroid Build Coastguard Worker            * prototype */
431*08b48e0bSAndroid Build Coastguard Worker           FunctionType *FT = Callee->getFunctionType();
432*08b48e0bSAndroid Build Coastguard Worker 
433*08b48e0bSAndroid Build Coastguard Worker           isStrstr &=
434*08b48e0bSAndroid Build Coastguard Worker               FT->getNumParams() == 2 &&
435*08b48e0bSAndroid Build Coastguard Worker               FT->getParamType(0) == FT->getParamType(1) &&
436*08b48e0bSAndroid Build Coastguard Worker               FT->getParamType(0) ==
437*08b48e0bSAndroid Build Coastguard Worker                   IntegerType::getInt8Ty(M.getContext())->getPointerTo(0);
438*08b48e0bSAndroid Build Coastguard Worker           isStrcmp &=
439*08b48e0bSAndroid Build Coastguard Worker               FT->getNumParams() == 2 && FT->getReturnType()->isIntegerTy(32) &&
440*08b48e0bSAndroid Build Coastguard Worker               FT->getParamType(0) == FT->getParamType(1) &&
441*08b48e0bSAndroid Build Coastguard Worker               FT->getParamType(0) ==
442*08b48e0bSAndroid Build Coastguard Worker                   IntegerType::getInt8Ty(M.getContext())->getPointerTo(0);
443*08b48e0bSAndroid Build Coastguard Worker           isStrcasecmp &=
444*08b48e0bSAndroid Build Coastguard Worker               FT->getNumParams() == 2 && FT->getReturnType()->isIntegerTy(32) &&
445*08b48e0bSAndroid Build Coastguard Worker               FT->getParamType(0) == FT->getParamType(1) &&
446*08b48e0bSAndroid Build Coastguard Worker               FT->getParamType(0) ==
447*08b48e0bSAndroid Build Coastguard Worker                   IntegerType::getInt8Ty(M.getContext())->getPointerTo(0);
448*08b48e0bSAndroid Build Coastguard Worker           isMemcmp &= FT->getNumParams() == 3 &&
449*08b48e0bSAndroid Build Coastguard Worker                       FT->getReturnType()->isIntegerTy(32) &&
450*08b48e0bSAndroid Build Coastguard Worker                       FT->getParamType(0)->isPointerTy() &&
451*08b48e0bSAndroid Build Coastguard Worker                       FT->getParamType(1)->isPointerTy() &&
452*08b48e0bSAndroid Build Coastguard Worker                       FT->getParamType(2)->isIntegerTy();
453*08b48e0bSAndroid Build Coastguard Worker           isStrncmp &=
454*08b48e0bSAndroid Build Coastguard Worker               FT->getNumParams() == 3 && FT->getReturnType()->isIntegerTy(32) &&
455*08b48e0bSAndroid Build Coastguard Worker               FT->getParamType(0) == FT->getParamType(1) &&
456*08b48e0bSAndroid Build Coastguard Worker               FT->getParamType(0) ==
457*08b48e0bSAndroid Build Coastguard Worker                   IntegerType::getInt8Ty(M.getContext())->getPointerTo(0) &&
458*08b48e0bSAndroid Build Coastguard Worker               FT->getParamType(2)->isIntegerTy();
459*08b48e0bSAndroid Build Coastguard Worker           isStrncasecmp &=
460*08b48e0bSAndroid Build Coastguard Worker               FT->getNumParams() == 3 && FT->getReturnType()->isIntegerTy(32) &&
461*08b48e0bSAndroid Build Coastguard Worker               FT->getParamType(0) == FT->getParamType(1) &&
462*08b48e0bSAndroid Build Coastguard Worker               FT->getParamType(0) ==
463*08b48e0bSAndroid Build Coastguard Worker                   IntegerType::getInt8Ty(M.getContext())->getPointerTo(0) &&
464*08b48e0bSAndroid Build Coastguard Worker               FT->getParamType(2)->isIntegerTy();
465*08b48e0bSAndroid Build Coastguard Worker           isStdString &= FT->getNumParams() >= 2 &&
466*08b48e0bSAndroid Build Coastguard Worker                          FT->getParamType(0)->isPointerTy() &&
467*08b48e0bSAndroid Build Coastguard Worker                          FT->getParamType(1)->isPointerTy();
468*08b48e0bSAndroid Build Coastguard Worker 
469*08b48e0bSAndroid Build Coastguard Worker           if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp &&
470*08b48e0bSAndroid Build Coastguard Worker               !isStrncasecmp && !isIntMemcpy && !isStdString && !isStrstr)
471*08b48e0bSAndroid Build Coastguard Worker             continue;
472*08b48e0bSAndroid Build Coastguard Worker 
473*08b48e0bSAndroid Build Coastguard Worker           /* is a str{n,}{case,}cmp/memcmp, check if we have
474*08b48e0bSAndroid Build Coastguard Worker            * str{case,}cmp(x, "const") or str{case,}cmp("const", x)
475*08b48e0bSAndroid Build Coastguard Worker            * strn{case,}cmp(x, "const", ..) or strn{case,}cmp("const", x, ..)
476*08b48e0bSAndroid Build Coastguard Worker            * memcmp(x, "const", ..) or memcmp("const", x, ..) */
477*08b48e0bSAndroid Build Coastguard Worker           Value *Str1P = callInst->getArgOperand(0),
478*08b48e0bSAndroid Build Coastguard Worker                 *Str2P = callInst->getArgOperand(1);
479*08b48e0bSAndroid Build Coastguard Worker           std::string Str1, Str2;
480*08b48e0bSAndroid Build Coastguard Worker           StringRef   TmpStr;
481*08b48e0bSAndroid Build Coastguard Worker           bool        HasStr1;
482*08b48e0bSAndroid Build Coastguard Worker           getConstantStringInfo(Str1P, TmpStr);
483*08b48e0bSAndroid Build Coastguard Worker 
484*08b48e0bSAndroid Build Coastguard Worker           if (isStrstr || TmpStr.empty()) {
485*08b48e0bSAndroid Build Coastguard Worker 
486*08b48e0bSAndroid Build Coastguard Worker             HasStr1 = false;
487*08b48e0bSAndroid Build Coastguard Worker 
488*08b48e0bSAndroid Build Coastguard Worker           } else {
489*08b48e0bSAndroid Build Coastguard Worker 
490*08b48e0bSAndroid Build Coastguard Worker             HasStr1 = true;
491*08b48e0bSAndroid Build Coastguard Worker             Str1 = TmpStr.str();
492*08b48e0bSAndroid Build Coastguard Worker 
493*08b48e0bSAndroid Build Coastguard Worker           }
494*08b48e0bSAndroid Build Coastguard Worker 
495*08b48e0bSAndroid Build Coastguard Worker           bool HasStr2;
496*08b48e0bSAndroid Build Coastguard Worker           getConstantStringInfo(Str2P, TmpStr);
497*08b48e0bSAndroid Build Coastguard Worker           if (TmpStr.empty()) {
498*08b48e0bSAndroid Build Coastguard Worker 
499*08b48e0bSAndroid Build Coastguard Worker             HasStr2 = false;
500*08b48e0bSAndroid Build Coastguard Worker 
501*08b48e0bSAndroid Build Coastguard Worker           } else {
502*08b48e0bSAndroid Build Coastguard Worker 
503*08b48e0bSAndroid Build Coastguard Worker             HasStr2 = true;
504*08b48e0bSAndroid Build Coastguard Worker             Str2 = TmpStr.str();
505*08b48e0bSAndroid Build Coastguard Worker 
506*08b48e0bSAndroid Build Coastguard Worker           }
507*08b48e0bSAndroid Build Coastguard Worker 
508*08b48e0bSAndroid Build Coastguard Worker           if (debug)
509*08b48e0bSAndroid Build Coastguard Worker             fprintf(stderr, "F:%s %p(%s)->\"%s\"(%s) %p(%s)->\"%s\"(%s)\n",
510*08b48e0bSAndroid Build Coastguard Worker                     FuncName.c_str(), (void *)Str1P,
511*08b48e0bSAndroid Build Coastguard Worker                     Str1P->getName().str().c_str(), Str1.c_str(),
512*08b48e0bSAndroid Build Coastguard Worker                     HasStr1 == true ? "true" : "false", (void *)Str2P,
513*08b48e0bSAndroid Build Coastguard Worker                     Str2P->getName().str().c_str(), Str2.c_str(),
514*08b48e0bSAndroid Build Coastguard Worker                     HasStr2 == true ? "true" : "false");
515*08b48e0bSAndroid Build Coastguard Worker 
516*08b48e0bSAndroid Build Coastguard Worker           // we handle the 2nd parameter first because of llvm memcpy
517*08b48e0bSAndroid Build Coastguard Worker           if (!HasStr2) {
518*08b48e0bSAndroid Build Coastguard Worker 
519*08b48e0bSAndroid Build Coastguard Worker             auto *Ptr = dyn_cast<ConstantExpr>(Str2P);
520*08b48e0bSAndroid Build Coastguard Worker             if (Ptr && Ptr->getOpcode() == Instruction::GetElementPtr) {
521*08b48e0bSAndroid Build Coastguard Worker 
522*08b48e0bSAndroid Build Coastguard Worker               if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {
523*08b48e0bSAndroid Build Coastguard Worker 
524*08b48e0bSAndroid Build Coastguard Worker                 if (Var->hasInitializer()) {
525*08b48e0bSAndroid Build Coastguard Worker 
526*08b48e0bSAndroid Build Coastguard Worker                   if (auto *Array =
527*08b48e0bSAndroid Build Coastguard Worker                           dyn_cast<ConstantDataArray>(Var->getInitializer())) {
528*08b48e0bSAndroid Build Coastguard Worker 
529*08b48e0bSAndroid Build Coastguard Worker                     HasStr2 = true;
530*08b48e0bSAndroid Build Coastguard Worker                     Str2 = Array->getRawDataValues().str();
531*08b48e0bSAndroid Build Coastguard Worker 
532*08b48e0bSAndroid Build Coastguard Worker                   }
533*08b48e0bSAndroid Build Coastguard Worker 
534*08b48e0bSAndroid Build Coastguard Worker                 }
535*08b48e0bSAndroid Build Coastguard Worker 
536*08b48e0bSAndroid Build Coastguard Worker               }
537*08b48e0bSAndroid Build Coastguard Worker 
538*08b48e0bSAndroid Build Coastguard Worker             }
539*08b48e0bSAndroid Build Coastguard Worker 
540*08b48e0bSAndroid Build Coastguard Worker           }
541*08b48e0bSAndroid Build Coastguard Worker 
542*08b48e0bSAndroid Build Coastguard Worker           // for the internal memcpy routine we only care for the second
543*08b48e0bSAndroid Build Coastguard Worker           // parameter and are not reporting anything.
544*08b48e0bSAndroid Build Coastguard Worker           if (isIntMemcpy == true) {
545*08b48e0bSAndroid Build Coastguard Worker 
546*08b48e0bSAndroid Build Coastguard Worker             if (HasStr2 == true) {
547*08b48e0bSAndroid Build Coastguard Worker 
548*08b48e0bSAndroid Build Coastguard Worker               Value       *op2 = callInst->getArgOperand(2);
549*08b48e0bSAndroid Build Coastguard Worker               ConstantInt *ilen = dyn_cast<ConstantInt>(op2);
550*08b48e0bSAndroid Build Coastguard Worker               if (ilen) {
551*08b48e0bSAndroid Build Coastguard Worker 
552*08b48e0bSAndroid Build Coastguard Worker                 uint64_t literalLength = Str2.length();
553*08b48e0bSAndroid Build Coastguard Worker                 uint64_t optLength = ilen->getZExtValue();
554*08b48e0bSAndroid Build Coastguard Worker                 if (optLength > literalLength + 1) {
555*08b48e0bSAndroid Build Coastguard Worker 
556*08b48e0bSAndroid Build Coastguard Worker                   optLength = Str2.length() + 1;
557*08b48e0bSAndroid Build Coastguard Worker 
558*08b48e0bSAndroid Build Coastguard Worker                 }
559*08b48e0bSAndroid Build Coastguard Worker 
560*08b48e0bSAndroid Build Coastguard Worker                 if (literalLength + 1 == optLength) {
561*08b48e0bSAndroid Build Coastguard Worker 
562*08b48e0bSAndroid Build Coastguard Worker                   Str2.append("\0", 1);  // add null byte
563*08b48e0bSAndroid Build Coastguard Worker 
564*08b48e0bSAndroid Build Coastguard Worker                 }
565*08b48e0bSAndroid Build Coastguard Worker 
566*08b48e0bSAndroid Build Coastguard Worker               }
567*08b48e0bSAndroid Build Coastguard Worker 
568*08b48e0bSAndroid Build Coastguard Worker               valueMap[Str1P] = new std::string(Str2);
569*08b48e0bSAndroid Build Coastguard Worker 
570*08b48e0bSAndroid Build Coastguard Worker               if (debug) {
571*08b48e0bSAndroid Build Coastguard Worker 
572*08b48e0bSAndroid Build Coastguard Worker                 fprintf(stderr, "Saved: %s for %p\n", Str2.c_str(),
573*08b48e0bSAndroid Build Coastguard Worker                         (void *)Str1P);
574*08b48e0bSAndroid Build Coastguard Worker 
575*08b48e0bSAndroid Build Coastguard Worker               }
576*08b48e0bSAndroid Build Coastguard Worker 
577*08b48e0bSAndroid Build Coastguard Worker               continue;
578*08b48e0bSAndroid Build Coastguard Worker 
579*08b48e0bSAndroid Build Coastguard Worker             }
580*08b48e0bSAndroid Build Coastguard Worker 
581*08b48e0bSAndroid Build Coastguard Worker             continue;
582*08b48e0bSAndroid Build Coastguard Worker 
583*08b48e0bSAndroid Build Coastguard Worker           }
584*08b48e0bSAndroid Build Coastguard Worker 
585*08b48e0bSAndroid Build Coastguard Worker           // Neither a literal nor a global variable?
586*08b48e0bSAndroid Build Coastguard Worker           // maybe it is a local variable that we saved
587*08b48e0bSAndroid Build Coastguard Worker           if (!HasStr2) {
588*08b48e0bSAndroid Build Coastguard Worker 
589*08b48e0bSAndroid Build Coastguard Worker             std::string *strng = valueMap[Str2P];
590*08b48e0bSAndroid Build Coastguard Worker             if (strng && !strng->empty()) {
591*08b48e0bSAndroid Build Coastguard Worker 
592*08b48e0bSAndroid Build Coastguard Worker               Str2 = *strng;
593*08b48e0bSAndroid Build Coastguard Worker               HasStr2 = true;
594*08b48e0bSAndroid Build Coastguard Worker               if (debug)
595*08b48e0bSAndroid Build Coastguard Worker                 fprintf(stderr, "Filled2: %s for %p\n", strng->c_str(),
596*08b48e0bSAndroid Build Coastguard Worker                         (void *)Str2P);
597*08b48e0bSAndroid Build Coastguard Worker 
598*08b48e0bSAndroid Build Coastguard Worker             }
599*08b48e0bSAndroid Build Coastguard Worker 
600*08b48e0bSAndroid Build Coastguard Worker           }
601*08b48e0bSAndroid Build Coastguard Worker 
602*08b48e0bSAndroid Build Coastguard Worker           if (!HasStr1) {
603*08b48e0bSAndroid Build Coastguard Worker 
604*08b48e0bSAndroid Build Coastguard Worker             auto Ptr = dyn_cast<ConstantExpr>(Str1P);
605*08b48e0bSAndroid Build Coastguard Worker 
606*08b48e0bSAndroid Build Coastguard Worker             if (Ptr && Ptr->getOpcode() == Instruction::GetElementPtr) {
607*08b48e0bSAndroid Build Coastguard Worker 
608*08b48e0bSAndroid Build Coastguard Worker               if (auto *Var = dyn_cast<GlobalVariable>(Ptr->getOperand(0))) {
609*08b48e0bSAndroid Build Coastguard Worker 
610*08b48e0bSAndroid Build Coastguard Worker                 if (Var->hasInitializer()) {
611*08b48e0bSAndroid Build Coastguard Worker 
612*08b48e0bSAndroid Build Coastguard Worker                   if (auto *Array =
613*08b48e0bSAndroid Build Coastguard Worker                           dyn_cast<ConstantDataArray>(Var->getInitializer())) {
614*08b48e0bSAndroid Build Coastguard Worker 
615*08b48e0bSAndroid Build Coastguard Worker                     HasStr1 = true;
616*08b48e0bSAndroid Build Coastguard Worker                     Str1 = Array->getRawDataValues().str();
617*08b48e0bSAndroid Build Coastguard Worker 
618*08b48e0bSAndroid Build Coastguard Worker                   }
619*08b48e0bSAndroid Build Coastguard Worker 
620*08b48e0bSAndroid Build Coastguard Worker                 }
621*08b48e0bSAndroid Build Coastguard Worker 
622*08b48e0bSAndroid Build Coastguard Worker               }
623*08b48e0bSAndroid Build Coastguard Worker 
624*08b48e0bSAndroid Build Coastguard Worker             }
625*08b48e0bSAndroid Build Coastguard Worker 
626*08b48e0bSAndroid Build Coastguard Worker           }
627*08b48e0bSAndroid Build Coastguard Worker 
628*08b48e0bSAndroid Build Coastguard Worker           // Neither a literal nor a global variable?
629*08b48e0bSAndroid Build Coastguard Worker           // maybe it is a local variable that we saved
630*08b48e0bSAndroid Build Coastguard Worker           if (!HasStr1) {
631*08b48e0bSAndroid Build Coastguard Worker 
632*08b48e0bSAndroid Build Coastguard Worker             std::string *strng = valueMap[Str1P];
633*08b48e0bSAndroid Build Coastguard Worker             if (strng && !strng->empty()) {
634*08b48e0bSAndroid Build Coastguard Worker 
635*08b48e0bSAndroid Build Coastguard Worker               Str1 = *strng;
636*08b48e0bSAndroid Build Coastguard Worker               HasStr1 = true;
637*08b48e0bSAndroid Build Coastguard Worker               if (debug)
638*08b48e0bSAndroid Build Coastguard Worker                 fprintf(stderr, "Filled1: %s for %p\n", strng->c_str(),
639*08b48e0bSAndroid Build Coastguard Worker                         (void *)Str1P);
640*08b48e0bSAndroid Build Coastguard Worker 
641*08b48e0bSAndroid Build Coastguard Worker             }
642*08b48e0bSAndroid Build Coastguard Worker 
643*08b48e0bSAndroid Build Coastguard Worker           }
644*08b48e0bSAndroid Build Coastguard Worker 
645*08b48e0bSAndroid Build Coastguard Worker           /* handle cases of one string is const, one string is variable */
646*08b48e0bSAndroid Build Coastguard Worker           if (!(HasStr1 ^ HasStr2)) continue;
647*08b48e0bSAndroid Build Coastguard Worker 
648*08b48e0bSAndroid Build Coastguard Worker           std::string thestring;
649*08b48e0bSAndroid Build Coastguard Worker 
650*08b48e0bSAndroid Build Coastguard Worker           if (HasStr1)
651*08b48e0bSAndroid Build Coastguard Worker             thestring = Str1;
652*08b48e0bSAndroid Build Coastguard Worker           else
653*08b48e0bSAndroid Build Coastguard Worker             thestring = Str2;
654*08b48e0bSAndroid Build Coastguard Worker 
655*08b48e0bSAndroid Build Coastguard Worker           optLen = thestring.length();
656*08b48e0bSAndroid Build Coastguard Worker 
657*08b48e0bSAndroid Build Coastguard Worker           if (optLen < 2 || (optLen == 2 && !thestring[1])) { continue; }
658*08b48e0bSAndroid Build Coastguard Worker 
659*08b48e0bSAndroid Build Coastguard Worker           if (isMemcmp || isStrncmp || isStrncasecmp) {
660*08b48e0bSAndroid Build Coastguard Worker 
661*08b48e0bSAndroid Build Coastguard Worker             Value       *op2 = callInst->getArgOperand(2);
662*08b48e0bSAndroid Build Coastguard Worker             ConstantInt *ilen = dyn_cast<ConstantInt>(op2);
663*08b48e0bSAndroid Build Coastguard Worker 
664*08b48e0bSAndroid Build Coastguard Worker             if (ilen) {
665*08b48e0bSAndroid Build Coastguard Worker 
666*08b48e0bSAndroid Build Coastguard Worker               uint64_t literalLength = optLen;
667*08b48e0bSAndroid Build Coastguard Worker               optLen = ilen->getZExtValue();
668*08b48e0bSAndroid Build Coastguard Worker               if (optLen > thestring.length() + 1) {
669*08b48e0bSAndroid Build Coastguard Worker 
670*08b48e0bSAndroid Build Coastguard Worker                 optLen = thestring.length() + 1;
671*08b48e0bSAndroid Build Coastguard Worker 
672*08b48e0bSAndroid Build Coastguard Worker               }
673*08b48e0bSAndroid Build Coastguard Worker 
674*08b48e0bSAndroid Build Coastguard Worker               if (optLen < 2) { continue; }
675*08b48e0bSAndroid Build Coastguard Worker               if (literalLength + 1 == optLen) {  // add null byte
676*08b48e0bSAndroid Build Coastguard Worker 
677*08b48e0bSAndroid Build Coastguard Worker                 thestring.append("\0", 1);
678*08b48e0bSAndroid Build Coastguard Worker 
679*08b48e0bSAndroid Build Coastguard Worker               }
680*08b48e0bSAndroid Build Coastguard Worker 
681*08b48e0bSAndroid Build Coastguard Worker             }
682*08b48e0bSAndroid Build Coastguard Worker 
683*08b48e0bSAndroid Build Coastguard Worker           }
684*08b48e0bSAndroid Build Coastguard Worker 
685*08b48e0bSAndroid Build Coastguard Worker           // add null byte if this is a string compare function and a null
686*08b48e0bSAndroid Build Coastguard Worker           // was not already added
687*08b48e0bSAndroid Build Coastguard Worker           if (!isMemcmp) {
688*08b48e0bSAndroid Build Coastguard Worker 
689*08b48e0bSAndroid Build Coastguard Worker             /*
690*08b48e0bSAndroid Build Coastguard Worker                         if (addedNull == false && thestring[optLen - 1] != '\0')
691*08b48e0bSAndroid Build Coastguard Worker                {
692*08b48e0bSAndroid Build Coastguard Worker 
693*08b48e0bSAndroid Build Coastguard Worker                           thestring.append("\0", 1);  // add null byte
694*08b48e0bSAndroid Build Coastguard Worker                           optLen++;
695*08b48e0bSAndroid Build Coastguard Worker 
696*08b48e0bSAndroid Build Coastguard Worker                         }
697*08b48e0bSAndroid Build Coastguard Worker 
698*08b48e0bSAndroid Build Coastguard Worker             */
699*08b48e0bSAndroid Build Coastguard Worker             if (!isStdString && thestring.find('\0', 0) != std::string::npos) {
700*08b48e0bSAndroid Build Coastguard Worker 
701*08b48e0bSAndroid Build Coastguard Worker               // ensure we do not have garbage
702*08b48e0bSAndroid Build Coastguard Worker               size_t offset = thestring.find('\0', 0);
703*08b48e0bSAndroid Build Coastguard Worker               if (offset + 1 < optLen) optLen = offset + 1;
704*08b48e0bSAndroid Build Coastguard Worker               thestring = thestring.substr(0, optLen);
705*08b48e0bSAndroid Build Coastguard Worker 
706*08b48e0bSAndroid Build Coastguard Worker             }
707*08b48e0bSAndroid Build Coastguard Worker 
708*08b48e0bSAndroid Build Coastguard Worker           }
709*08b48e0bSAndroid Build Coastguard Worker 
710*08b48e0bSAndroid Build Coastguard Worker           // we take the longer string, even if the compare was to a
711*08b48e0bSAndroid Build Coastguard Worker           // shorter part. Note that depending on the optimizer of the
712*08b48e0bSAndroid Build Coastguard Worker           // compiler this can be wrong, but it is more likely that this
713*08b48e0bSAndroid Build Coastguard Worker           // is helping the fuzzer
714*08b48e0bSAndroid Build Coastguard Worker           if (optLen != thestring.length()) optLen = thestring.length();
715*08b48e0bSAndroid Build Coastguard Worker           if (optLen > MAX_AUTO_EXTRA) optLen = MAX_AUTO_EXTRA;
716*08b48e0bSAndroid Build Coastguard Worker           if (optLen < 3)  // too short? skip
717*08b48e0bSAndroid Build Coastguard Worker             continue;
718*08b48e0bSAndroid Build Coastguard Worker 
719*08b48e0bSAndroid Build Coastguard Worker           ptr = (char *)thestring.c_str();
720*08b48e0bSAndroid Build Coastguard Worker 
721*08b48e0bSAndroid Build Coastguard Worker           dict2file((u8 *)ptr, optLen);
722*08b48e0bSAndroid Build Coastguard Worker           found++;
723*08b48e0bSAndroid Build Coastguard Worker 
724*08b48e0bSAndroid Build Coastguard Worker         }
725*08b48e0bSAndroid Build Coastguard Worker 
726*08b48e0bSAndroid Build Coastguard Worker       }
727*08b48e0bSAndroid Build Coastguard Worker 
728*08b48e0bSAndroid Build Coastguard Worker     }
729*08b48e0bSAndroid Build Coastguard Worker 
730*08b48e0bSAndroid Build Coastguard Worker   }
731*08b48e0bSAndroid Build Coastguard Worker 
732*08b48e0bSAndroid Build Coastguard Worker   of.close();
733*08b48e0bSAndroid Build Coastguard Worker 
734*08b48e0bSAndroid Build Coastguard Worker   /* Say something nice. */
735*08b48e0bSAndroid Build Coastguard Worker 
736*08b48e0bSAndroid Build Coastguard Worker   if (!be_quiet) {
737*08b48e0bSAndroid Build Coastguard Worker 
738*08b48e0bSAndroid Build Coastguard Worker     if (!found)
739*08b48e0bSAndroid Build Coastguard Worker       OKF("No entries for a dictionary found.");
740*08b48e0bSAndroid Build Coastguard Worker     else
741*08b48e0bSAndroid Build Coastguard Worker       OKF("Wrote %d entries to the dictionary file.\n", found);
742*08b48e0bSAndroid Build Coastguard Worker 
743*08b48e0bSAndroid Build Coastguard Worker   }
744*08b48e0bSAndroid Build Coastguard Worker 
745*08b48e0bSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR >= 11                        /* use new pass manager */
746*08b48e0bSAndroid Build Coastguard Worker   auto PA = PreservedAnalyses::all();
747*08b48e0bSAndroid Build Coastguard Worker   return PA;
748*08b48e0bSAndroid Build Coastguard Worker #else
749*08b48e0bSAndroid Build Coastguard Worker   return true;
750*08b48e0bSAndroid Build Coastguard Worker #endif
751*08b48e0bSAndroid Build Coastguard Worker 
752*08b48e0bSAndroid Build Coastguard Worker }
753*08b48e0bSAndroid Build Coastguard Worker 
754*08b48e0bSAndroid Build Coastguard Worker #if LLVM_VERSION_MAJOR < 11                         /* use old pass manager */
755*08b48e0bSAndroid Build Coastguard Worker static void registerAFLdict2filePass(const PassManagerBuilder &,
756*08b48e0bSAndroid Build Coastguard Worker                                      legacy::PassManagerBase &PM) {
757*08b48e0bSAndroid Build Coastguard Worker 
758*08b48e0bSAndroid Build Coastguard Worker   PM.add(new AFLdict2filePass());
759*08b48e0bSAndroid Build Coastguard Worker 
760*08b48e0bSAndroid Build Coastguard Worker }
761*08b48e0bSAndroid Build Coastguard Worker 
762*08b48e0bSAndroid Build Coastguard Worker static RegisterPass<AFLdict2filePass> X("afl-dict2file",
763*08b48e0bSAndroid Build Coastguard Worker                                         "AFL++ dict2file instrumentation pass",
764*08b48e0bSAndroid Build Coastguard Worker                                         false, false);
765*08b48e0bSAndroid Build Coastguard Worker 
766*08b48e0bSAndroid Build Coastguard Worker static RegisterStandardPasses RegisterAFLdict2filePass(
767*08b48e0bSAndroid Build Coastguard Worker     PassManagerBuilder::EP_OptimizerLast, registerAFLdict2filePass);
768*08b48e0bSAndroid Build Coastguard Worker 
769*08b48e0bSAndroid Build Coastguard Worker static RegisterStandardPasses RegisterAFLdict2filePass0(
770*08b48e0bSAndroid Build Coastguard Worker     PassManagerBuilder::EP_EnabledOnOptLevel0, registerAFLdict2filePass);
771*08b48e0bSAndroid Build Coastguard Worker 
772*08b48e0bSAndroid Build Coastguard Worker #endif
773*08b48e0bSAndroid Build Coastguard Worker 
774