1 // the following must precede stdio (woo, thanks msft)
2 #if defined(_MSC_VER) && _MSC_VER < 1900
3 #define _CRT_SECURE_NO_WARNINGS
4 #endif
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <inttypes.h>
9
10 #include <capstone/capstone.h>
11
12 int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
13
14
15 struct platform {
16 cs_arch arch;
17 cs_mode mode;
18 const char *comment;
19 };
20
21 static FILE *outfile = NULL;
22
23 static struct platform platforms[] = {
24 {
25 // item 0
26 CS_ARCH_X86,
27 CS_MODE_32,
28 "X86 32 (Intel syntax)"
29 },
30 {
31 // item 1
32 CS_ARCH_X86,
33 CS_MODE_64,
34 "X86 64 (Intel syntax)"
35 },
36 {
37 // item 2
38 CS_ARCH_ARM,
39 CS_MODE_ARM,
40 "ARM"
41 },
42 {
43 // item 3
44 CS_ARCH_ARM,
45 CS_MODE_THUMB,
46 "THUMB"
47 },
48 {
49 // item 4
50 CS_ARCH_ARM,
51 (cs_mode)(CS_MODE_ARM + CS_MODE_V8),
52 "Arm-V8"
53 },
54 {
55 // item 5
56 CS_ARCH_ARM,
57 (cs_mode)(CS_MODE_THUMB+CS_MODE_V8),
58 "THUMB+V8"
59 },
60 {
61 // item 6
62 CS_ARCH_ARM,
63 (cs_mode)(CS_MODE_THUMB + CS_MODE_MCLASS),
64 "Thumb-MClass"
65 },
66 {
67 // item 7
68 CS_ARCH_ARM64,
69 (cs_mode)0,
70 "ARM-64"
71 },
72 {
73 // item 8
74 CS_ARCH_MIPS,
75 (cs_mode)(CS_MODE_MIPS32 + CS_MODE_BIG_ENDIAN),
76 "MIPS-32 (Big-endian)"
77 },
78 {
79 // item 9
80 CS_ARCH_MIPS,
81 (cs_mode)(CS_MODE_MIPS32 + CS_MODE_MICRO),
82 "MIPS-32 (micro)"
83 },
84 {
85 //item 10
86 CS_ARCH_MIPS,
87 CS_MODE_MIPS64,
88 "MIPS-64-EL (Little-endian)"
89 },
90 {
91 //item 11
92 CS_ARCH_MIPS,
93 CS_MODE_MIPS32,
94 "MIPS-32-EL (Little-endian)"
95 },
96 {
97 //item 12
98 CS_ARCH_MIPS,
99 (cs_mode)(CS_MODE_MIPS64 + CS_MODE_BIG_ENDIAN),
100 "MIPS-64 (Big-endian)"
101 },
102 {
103 //item 13
104 CS_ARCH_MIPS,
105 (cs_mode)(CS_MODE_MIPS32 + CS_MODE_MICRO + CS_MODE_BIG_ENDIAN),
106 "MIPS-32 | Micro (Big-endian)"
107 },
108 {
109 //item 14
110 CS_ARCH_PPC,
111 CS_MODE_BIG_ENDIAN,
112 "PPC-64"
113 },
114 {
115 //item 15
116 CS_ARCH_SPARC,
117 CS_MODE_BIG_ENDIAN,
118 "Sparc"
119 },
120 {
121 //item 16
122 CS_ARCH_SPARC,
123 (cs_mode)(CS_MODE_BIG_ENDIAN + CS_MODE_V9),
124 "SparcV9"
125 },
126 {
127 //item 17
128 CS_ARCH_SYSZ,
129 (cs_mode)0,
130 "SystemZ"
131 },
132 {
133 //item 18
134 CS_ARCH_XCORE,
135 (cs_mode)0,
136 "XCore"
137 },
138 {
139 //item 19
140 CS_ARCH_MIPS,
141 (cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_BIG_ENDIAN),
142 "MIPS-32R6 (Big-endian)"
143 },
144 {
145 //item 20
146 CS_ARCH_MIPS,
147 (cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_MICRO + CS_MODE_BIG_ENDIAN),
148 "MIPS-32R6 (Micro+Big-endian)"
149 },
150 {
151 //item 21
152 CS_ARCH_MIPS,
153 CS_MODE_MIPS32R6,
154 "MIPS-32R6 (Little-endian)"
155 },
156 {
157 //item 22
158 CS_ARCH_MIPS,
159 (cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_MICRO),
160 "MIPS-32R6 (Micro+Little-endian)"
161 },
162 {
163 //item 23
164 CS_ARCH_M68K,
165 (cs_mode)0,
166 "M68K"
167 },
168 {
169 //item 24
170 CS_ARCH_M680X,
171 (cs_mode)CS_MODE_M680X_6809,
172 "M680X_M6809"
173 },
174 {
175 //item 25
176 CS_ARCH_EVM,
177 (cs_mode)0,
178 "EVM"
179 },
180 #ifdef CAPSTONE_HAS_MOS65XX
181 {
182 //item 26
183 CS_ARCH_MOS65XX,
184 (cs_mode)0,
185 "MOS65XX"
186 },
187 #endif
188 };
189
LLVMFuzzerTestOneInput(const uint8_t * Data,size_t Size)190 int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
191 csh handle;
192 cs_insn *all_insn;
193 cs_detail *detail;
194 cs_err err;
195
196 if (Size < 1) {
197 // 1 byte for arch choice
198 return 0;
199 } else if (Size > 0x1000) {
200 //limit input to 4kb
201 Size = 0x1000;
202 }
203
204 if (outfile == NULL) {
205 // we compute the output
206 outfile = fopen("/dev/null", "w");
207 if (outfile == NULL) {
208 return 0;
209 }
210 }
211
212 int platforms_len = sizeof(platforms)/sizeof(platforms[0]);
213 int i = (int)Data[0] % platforms_len;
214
215 err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
216 if (err) {
217 return 0;
218 }
219
220 cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
221
222 uint64_t address = 0x1000;
223 size_t count = cs_disasm(handle, Data+1, Size-1, address, 0, &all_insn);
224
225 if (count) {
226 size_t j;
227 unsigned int n;
228
229 for (j = 0; j < count; j++) {
230 cs_insn *i = &(all_insn[j]);
231 fprintf(outfile, "0x%"PRIx64":\t%s\t\t%s // insn-ID: %u, insn-mnem: %s\n",
232 i->address, i->mnemonic, i->op_str,
233 i->id, cs_insn_name(handle, i->id));
234
235 detail = i->detail;
236
237 if (detail->regs_read_count > 0) {
238 fprintf(outfile, "\tImplicit registers read: ");
239 for (n = 0; n < detail->regs_read_count; n++) {
240 fprintf(outfile, "%s ", cs_reg_name(handle, detail->regs_read[n]));
241 }
242 }
243
244 if (detail->regs_write_count > 0) {
245 fprintf(outfile, "\tImplicit registers modified: ");
246 for (n = 0; n < detail->regs_write_count; n++) {
247 fprintf(outfile, "%s ", cs_reg_name(handle, detail->regs_write[n]));
248 }
249 }
250
251 if (detail->groups_count > 0) {
252 fprintf(outfile, "\tThis instruction belongs to groups: ");
253 for (n = 0; n < detail->groups_count; n++) {
254 fprintf(outfile, "%s ", cs_group_name(handle, detail->groups[n]));
255 }
256 }
257 }
258
259 fprintf(outfile, "0x%"PRIx64":\n", all_insn[j-1].address + all_insn[j-1].size);
260 cs_free(all_insn, count);
261 }
262
263 cs_close(&handle);
264
265 return 0;
266 }
267