xref: /aosp_15_r20/external/capstone/suite/fuzz/fuzz_disasm.c (revision 9a0e4156d50a75a99ec4f1653a0e9602a5d45c18)
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