1 /* Capstone testing regression */
2 /* By Do Minh Tuan <tuanit96@gmail.com>, 02-2019 */
3
4
5 #include "helper.h"
6 #include "capstone_test.h"
7 #include <unistd.h>
8
9 static int counter;
10 static char **list_lines;
11 static int failed_setup;
12 static int size_lines;
13 static cs_mode issue_mode;
14 static int getDetail;
15 static int mc_mode;
16 static int e_flag;
17
setup_MC(void ** state)18 static int setup_MC(void **state)
19 {
20 csh *handle;
21 char **list_params;
22 int size_params;
23 int arch, mode;
24 int i, index, tmp_counter;
25
26 if (failed_setup) {
27 fprintf(stderr, "[ ERROR ] --- Invalid file to setup\n");
28 return -1;
29 }
30
31 tmp_counter = 0;
32 while (tmp_counter < size_lines && list_lines[tmp_counter][0] != '#')
33 tmp_counter++;
34
35 list_params = split(list_lines[tmp_counter] + 2, ", ", &size_params);
36 if (size_params != 3) {
37 fprintf(stderr, "[ ERROR ] --- Invalid options ( arch, mode, option )\n");
38 failed_setup = 1;
39 return -1;
40 }
41
42 arch = get_value(arches, NUMARCH, list_params[0]);
43 if (!strcmp(list_params[0], "CS_ARCH_ARM64"))
44 mc_mode = 2;
45 else
46 mc_mode = 1;
47
48 mode = 0;
49 for (i = 0; i < NUMMODE; ++i) {
50 if (strstr(list_params[1], modes[i].str)) {
51 mode += modes[i].value;
52 switch (modes[i].value) {
53 case CS_MODE_16:
54 mc_mode = 0;
55 break;
56 case CS_MODE_64:
57 mc_mode = 2;
58 break;
59 case CS_MODE_THUMB:
60 mc_mode = 1;
61 break;
62 default:
63 break;
64 }
65 }
66 }
67
68 if (arch == -1) {
69 fprintf(stderr, "[ ERROR ] --- Arch is not supported!\n");
70 failed_setup = 1;
71 return -1;
72 }
73
74 handle = (csh *)malloc(sizeof(csh));
75 if(cs_open(arch, mode, handle) != CS_ERR_OK) {
76 fprintf(stderr, "[ ERROR ] --- Cannot initialize capstone\n");
77 failed_setup = 1;
78 return -1;
79 }
80
81 for (i = 0; i < NUMOPTION; ++i) {
82 if (strstr(list_params[2], options[i].str)) {
83 if (cs_option(*handle, options[i].first_value, options[i].second_value) != CS_ERR_OK) {
84 fprintf(stderr, "[ ERROR ] --- Option is not supported for this arch/mode\n");
85 failed_setup = 1;
86 return -1;
87 }
88 }
89 }
90
91 *state = (void *)handle;
92 counter++;
93 if (e_flag == 0)
94 while (counter < size_lines && strncmp(list_lines[counter], "0x", 2))
95 counter++;
96 else
97 while (counter < size_lines && strncmp(list_lines[counter], "// 0x", 5))
98 counter++;
99
100 free_strs(list_params, size_params);
101 return 0;
102 }
103
test_MC(void ** state)104 static void test_MC(void **state)
105 {
106 if (e_flag == 1)
107 test_single_MC((csh *)*state, mc_mode, list_lines[counter] + 3);
108 else
109 test_single_MC((csh *)*state, mc_mode, list_lines[counter]);
110 }
111
teardown_MC(void ** state)112 static int teardown_MC(void **state)
113 {
114 cs_close(*state);
115 free(*state);
116 return 0;
117 }
118
setup_issue(void ** state)119 static int setup_issue(void **state)
120 {
121 csh *handle;
122 char **list_params;
123 int size_params;
124 int arch, mode;
125 int i, index, result;
126 char *(*function)(csh *, cs_mode, cs_insn*);
127
128 getDetail = 0;
129 failed_setup = 0;
130
131 if (e_flag == 0)
132 while (counter < size_lines && strncmp(list_lines[counter], "!# ", 3))
133 counter++; // get issue line
134 else
135 while (counter < size_lines && strncmp(list_lines[counter], "// !# ", 6))
136 counter++;
137
138 counter++;
139 if (e_flag == 0)
140 while (counter < size_lines && strncmp(list_lines[counter], "!#", 2))
141 counter++; // get arch line
142 else
143 while (counter < size_lines && strncmp(list_lines[counter], "// !# ", 6))
144 counter++;
145
146 if (e_flag == 0)
147 list_params = split(list_lines[counter] + 3, ", ", &size_params);
148 else
149 list_params = split(list_lines[counter] + 6, ", ", &size_params);
150
151 arch = get_value(arches, NUMARCH, list_params[0]);
152
153 if (!strcmp(list_params[0], "CS_ARCH_ARM64"))
154 mc_mode = 2;
155 else
156 mc_mode = 1;
157
158 mode = 0;
159 for (i = 0; i < NUMMODE; ++i) {
160 if (strstr(list_params[1], modes[i].str)) {
161 mode += modes[i].value;
162 switch (modes[i].value) {
163 case CS_MODE_16:
164 mc_mode = 0;
165 break;
166 case CS_MODE_64:
167 mc_mode = 2;
168 break;
169 case CS_MODE_THUMB:
170 mc_mode = 1;
171 break;
172 default:
173 break;
174 }
175 }
176 }
177
178 if (arch == -1) {
179 fprintf(stderr, "[ ERROR ] --- Arch is not supported!\n");
180 failed_setup = 1;
181 return -1;
182 }
183
184 handle = (csh *)calloc(1, sizeof(csh));
185 if(cs_open(arch, mode, handle) != CS_ERR_OK) {
186 fprintf(stderr, "[ ERROR ] --- Cannot initialize capstone\n");
187 failed_setup = 1;
188 return -1;
189 }
190
191 for (i = 0; i < NUMOPTION; ++i) {
192 if (strstr(list_params[2], options[i].str)) {
193 if (cs_option(*handle, options[i].first_value, options[i].second_value) != CS_ERR_OK) {
194 fprintf(stderr, "[ ERROR ] --- Option is not supported for this arch/mode\n");
195 failed_setup = 1;
196 return -1;
197 }
198
199 if (i == 0) {
200 result = set_function(arch);
201 if (result == -1) {
202 fprintf(stderr, "[ ERROR ] --- Cannot get details\n");
203 failed_setup = 1;
204 return -1;
205 }
206
207 getDetail = 1;
208 }
209 }
210 }
211
212 *state = (void *)handle;
213 issue_mode = mode;
214
215 if (e_flag == 0)
216 while (counter < size_lines && strncmp(list_lines[counter], "0x", 2))
217 counter++;
218 else
219 while (counter < size_lines && strncmp(list_lines[counter], "// 0x", 5))
220 counter++;
221
222 free_strs(list_params, size_params);
223 return 0;
224 }
225
test_issue(void ** state)226 static void test_issue(void **state)
227 {
228 if (e_flag == 0)
229 test_single_issue((csh *)*state, issue_mode, list_lines[counter], getDetail);
230 else
231 test_single_issue((csh *)*state, issue_mode, list_lines[counter] + 3, getDetail);
232
233 return;
234 }
235
teardown_issue(void ** state)236 static int teardown_issue(void **state)
237 {
238 if (e_flag == 0)
239 while (counter < size_lines && strncmp(list_lines[counter], "!# ", 3))
240 counter++;
241 else
242 while (counter < size_lines && strncmp(list_lines[counter], "// !# ", 6))
243 counter++;
244
245 cs_close(*state);
246 free(*state);
247 function = NULL;
248 return 0;
249 }
250
test_file(const char * filename)251 static void test_file(const char *filename)
252 {
253 int size, i;
254 char **list_str;
255 char *content, *tmp;
256 struct CMUnitTest *tests;
257 int issue_num, number_of_tests;
258
259 printf("[+] TARGET: %s\n", filename);
260 content = readfile(filename);
261 counter = 0;
262 failed_setup = 0;
263 function = NULL;
264
265 if (strstr(filename, "issue")) {
266 number_of_tests = 0;
267 list_lines = split(content, "\n", &size_lines);
268 tests = NULL;
269 for (i = 0; i < size_lines; ++i) {
270 if ((!strncmp(list_lines[i], "// !# issue", 11) && e_flag == 1) ||
271 (!strncmp(list_lines[i], "!# issue", 8) && e_flag == 0)) {
272 tests = (struct CMUnitTest *)realloc(tests, sizeof(struct CMUnitTest) * (number_of_tests + 1));
273 tests[number_of_tests] = (struct CMUnitTest)cmocka_unit_test_setup_teardown(test_issue, setup_issue, teardown_issue);
274 tests[number_of_tests].name = strdup(list_lines[i]);
275 number_of_tests ++;
276 }
277 }
278
279 _cmocka_run_group_tests("Testing issues", tests, number_of_tests, NULL, NULL);
280 } else {
281 list_lines = split(content, "\n", &size_lines);
282 number_of_tests = 0;
283
284 tests = NULL;
285 for (i = 1; i < size_lines; ++i) {
286 if ((!strncmp(list_lines[i], "// 0x", 5) && e_flag == 1) || (!strncmp(list_lines[i], "0x", 2) && e_flag == 0)) {
287 tmp = (char *)malloc(sizeof(char) * 100);
288 sprintf(tmp, "Line %d", i+1);
289 tests = (struct CMUnitTest *)realloc(tests, sizeof(struct CMUnitTest) * (number_of_tests + 1));
290 tests[number_of_tests] = (struct CMUnitTest)cmocka_unit_test_setup_teardown(test_MC, setup_MC, teardown_MC);
291 tests[number_of_tests].name = tmp;
292 number_of_tests ++;
293 }
294 }
295
296 _cmocka_run_group_tests("Testing MC", tests, number_of_tests, NULL, NULL);
297 }
298
299 printf("[+] DONE: %s\n", filename);
300 printf("[!] Noted:\n[ ERROR ] --- \"<capstone result>\" != \"<user result>\"\n");
301 printf("\n\n");
302 free_strs(list_lines, size_lines);
303 }
304
test_folder(const char * folder)305 static void test_folder(const char *folder)
306 {
307 char **files;
308 int num_files, i;
309
310 files = NULL;
311 num_files = 0;
312 listdir(folder, &files, &num_files);
313 for (i = 0; i < num_files; ++i) {
314 if (strcmp("cs", get_filename_ext(files[i])))
315 continue;
316 test_file(files[i]);
317 }
318 }
319
main(int argc,char * argv[])320 int main(int argc, char *argv[])
321 {
322 int opt, flag;
323
324 flag = 0;
325 e_flag = 0;
326
327 while ((opt = getopt(argc, argv, "ef:d:")) > 0) {
328 switch (opt) {
329 case 'f':
330 test_file(optarg);
331 flag = 1;
332 break;
333 case 'd':
334 test_folder(optarg);
335 flag = 1;
336 break;
337 case 'e':
338 e_flag = 1;
339 break;
340 default:
341 printf("Usage: %s [-e] [-f <file_name.cs>] [-d <directory>]\n", argv[0]);
342 exit(-1);
343 }
344 }
345
346 if (flag == 0) {
347 printf("Usage: %s [-e] [-f <file_name.cs>] [-d <directory>]\n", argv[0]);
348 exit(-1);
349 }
350
351 return 0;
352 }
353