1 
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <inttypes.h>
5 #include <assert.h>
6 
7 #include <capstone/capstone.h>
8 
9 
10 struct platform {
11     cs_arch arch;
12     cs_mode mode;
13     char *comment;
14 };
15 
16 FILE * outfile = NULL;
17 
18 struct platform platforms[] = {
19     {
20         // item 0
21         CS_ARCH_X86,
22         CS_MODE_32,
23         "X86 32 (Intel syntax)"
24     },
25     {
26         // item 1
27         CS_ARCH_X86,
28         CS_MODE_64,
29         "X86 64 (Intel syntax)"
30     },
31     {
32         // item 2
33         CS_ARCH_ARM,
34         CS_MODE_ARM,
35         "ARM"
36     },
37     {
38         // item 3
39         CS_ARCH_ARM,
40         CS_MODE_THUMB,
41         "THUMB"
42     },
43     {
44         // item 4
45         CS_ARCH_ARM,
46         (cs_mode)(CS_MODE_ARM + CS_MODE_V8),
47         "Arm-V8"
48     },
49     {
50         // item 5
51         CS_ARCH_ARM,
52         (cs_mode)(CS_MODE_THUMB+CS_MODE_V8),
53         "THUMB+V8"
54     },
55     {
56         // item 6
57         CS_ARCH_ARM,
58         (cs_mode)(CS_MODE_THUMB + CS_MODE_MCLASS),
59         "Thumb-MClass"
60     },
61     {
62         // item 7
63         CS_ARCH_ARM64,
64         (cs_mode)0,
65         "ARM-64"
66     },
67     {
68         // item 8
69         CS_ARCH_MIPS,
70         (cs_mode)(CS_MODE_MIPS32 + CS_MODE_BIG_ENDIAN),
71         "MIPS-32 (Big-endian)"
72     },
73     {
74         // item 9
75         CS_ARCH_MIPS,
76         (cs_mode)(CS_MODE_MIPS32 + CS_MODE_MICRO),
77         "MIPS-32 (micro)"
78     },
79     {
80         //item 10
81         CS_ARCH_MIPS,
82         CS_MODE_MIPS64,
83         "MIPS-64-EL (Little-endian)"
84     },
85     {
86         //item 11
87         CS_ARCH_MIPS,
88         CS_MODE_MIPS32,
89         "MIPS-32-EL (Little-endian)"
90     },
91     {
92         //item 12
93         CS_ARCH_MIPS,
94         (cs_mode)(CS_MODE_MIPS64 + CS_MODE_BIG_ENDIAN),
95         "MIPS-64 (Big-endian)"
96     },
97     {
98         //item 13
99         CS_ARCH_MIPS,
100         (cs_mode)(CS_MODE_MIPS32 + CS_MODE_MICRO + CS_MODE_BIG_ENDIAN),
101         "MIPS-32 | Micro (Big-endian)"
102     },
103     {
104         //item 14
105         CS_ARCH_PPC,
106         CS_MODE_BIG_ENDIAN,
107         "PPC-64"
108     },
109     {
110         //item 15
111         CS_ARCH_SPARC,
112         CS_MODE_BIG_ENDIAN,
113         "Sparc"
114     },
115     {
116         //item 16
117         CS_ARCH_SPARC,
118         (cs_mode)(CS_MODE_BIG_ENDIAN + CS_MODE_V9),
119         "SparcV9"
120     },
121     {
122         //item 17
123         CS_ARCH_SYSZ,
124         (cs_mode)0,
125         "SystemZ"
126     },
127     {
128         //item 18
129         CS_ARCH_XCORE,
130         (cs_mode)0,
131         "XCore"
132     },
133     {
134         //item 19
135         CS_ARCH_MIPS,
136         (cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_BIG_ENDIAN),
137         "MIPS-32R6 (Big-endian)"
138     },
139     {
140         //item 20
141         CS_ARCH_MIPS,
142         (cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_MICRO + CS_MODE_BIG_ENDIAN),
143         "MIPS-32R6 (Micro+Big-endian)"
144     },
145     {
146         //item 21
147         CS_ARCH_MIPS,
148         CS_MODE_MIPS32R6,
149         "MIPS-32R6 (Little-endian)"
150     },
151     {
152         //item 22
153         CS_ARCH_MIPS,
154         (cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_MICRO),
155         "MIPS-32R6 (Micro+Little-endian)"
156     },
157     {
158         //item 23
159         CS_ARCH_M68K,
160         (cs_mode)0,
161         "M68K"
162     },
163     {
164         //item 24
165         CS_ARCH_M680X,
166         (cs_mode)CS_MODE_M680X_6809,
167         "M680X_M6809"
168     },
169     {
170         //item 25
171         CS_ARCH_EVM,
172         (cs_mode)0,
173         "EVM"
174     },
175 };
176 
177 void LLVMFuzzerInit();
178 int LLVMFuzzerReturnOneInput(const uint8_t *Data, size_t Size, char * AssemblyText);
179 
LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)180 int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
181     csh handle;
182     cs_insn *insn;
183     cs_err err;
184     const uint8_t **Datap = &Data;
185     size_t * Sizep = &Size;
186     uint64_t address = 0x1000;
187     char LLVMAssemblyText[80];
188     char CapstoneAssemblyText[80];
189 
190     if (Size < 1) {
191         // 1 byte for arch choice
192         return 0;
193     } else if (Size > 0x1000) {
194         //limit input to 4kb
195         Size = 0x1000;
196     }
197     if (outfile == NULL) {
198         // we compute the output
199         outfile = fopen("/dev/null", "w");
200         if (outfile == NULL) {
201             return 0;
202         }
203         LLVMFuzzerInit();
204     }
205 
206     if (Data[0] >= sizeof(platforms)/sizeof(platforms[0])) {
207         return 0;
208     }
209 
210     if (LLVMFuzzerReturnOneInput(Data, Size, LLVMAssemblyText) == 1) {
211         return 0;
212     }
213 
214     err = cs_open(platforms[Data[0]].arch, platforms[Data[0]].mode, &handle);
215     if (err) {
216         return 0;
217     }
218 
219     insn = cs_malloc(handle);
220     Data++;
221     Size--;
222     assert(insn);
223         if (cs_disasm_iter(handle, Datap, Sizep, &address, insn)) {
224             snprintf(CapstoneAssemblyText, 80, "\t%s\t%s", insn->mnemonic, insn->op_str);
225             if (strcmp(CapstoneAssemblyText, LLVMAssemblyText) != 0) {
226                 printf("capstone %s != llvm %s", CapstoneAssemblyText, LLVMAssemblyText);
227                 abort();
228             }
229         } else {
230             printf("capstone failed with llvm %s", LLVMAssemblyText);
231             abort();
232         }
233     cs_free(insn, 1);
234     cs_close(&handle);
235 
236     return 0;
237 }
238