Skip to content

Commit 3a0467c

Browse files
catenacyberaquynh
authored andcommitted
Use whole corpus for regression testing (capstone-engine#1302)
* Use whole corpus for regression testing * differetial fuzzing against llvm-mc * Download corpus from another repo
1 parent a69f788 commit 3a0467c

File tree

6 files changed

+374
-4
lines changed

6 files changed

+374
-4
lines changed

.travis.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ language: cpp
22
sudo: false
33
before_install:
44
- export LD_LIBRARY_PATH=`pwd`/tests/:$LD_LIBRARY_PATH
5+
before_script:
6+
- wget https://github.com/groundx/capstonefuzz/raw/master/corpus/corpus-libFuzzer-capstone_fuzz_disasmnext-latest.zip
7+
- unzip corpus-libFuzzer-capstone_fuzz_disasmnext-latest.zip -d suite/fuzz
58
script:
69
- ./make.sh
710
- make check

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ TESTS += test_basic.static test_detail.static test_arm.static test_arm64.static
461461
TESTS += test_m68k.static test_mips.static test_ppc.static test_sparc.static
462462
TESTS += test_systemz.static test_x86.static test_xcore.static test_m680x.static
463463
TESTS += test_skipdata test_skipdata.static test_iter.static test_evm.static
464-
check: $(TESTS) fuzztest
464+
check: $(TESTS) fuzztest fuzzallcorp
465465
test_%:
466466
./tests/$@ > /dev/null && echo OK || echo FAILED
467467

@@ -470,6 +470,9 @@ FUZZ_INPUTS = $(shell find suite/MC -type f -name '*.cs')
470470
fuzztest:
471471
./suite/fuzz/fuzz_disasm $(FUZZ_INPUTS)
472472

473+
fuzzallcorp:
474+
./suite/fuzz/fuzz_bindisasm suite/fuzz/corpus-libFuzzer-capstone_fuzz_disasmnext-latest/
475+
473476
$(OBJDIR)/%.o: %.c
474477
@mkdir -p $(@D)
475478
ifeq ($(V),0)

suite/fuzz/Makefile

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,15 @@ ARCHIVE = $(LIBDIR)/lib$(LIBNAME).$(AR_EXT)
3838

3939
.PHONY: all clean
4040

41-
SOURCES = fuzz_disasm.c drivermc.c fuzz_harness.c
41+
SOURCES = fuzz_disasm.c drivermc.c fuzz_harness.c driverbin.c
4242
OBJS = $(addprefix $(OBJDIR)/,$(SOURCES:.c=.o))
4343
BINARY = $(addprefix $(TESTDIR)/,fuzz_disasm$(BIN_EXT))
44+
BINARYBIN = $(addprefix $(TESTDIR)/,fuzz_bindisasm$(BIN_EXT))
4445

45-
all: $(BINARY)
46+
all: $(BINARY) $(BINARYBIN)
4647

4748
clean:
48-
rm -rf fuzz_harness $(OBJS) $(BINARY) $(OBJDIR)/lib$(LIBNAME).* $(OBJDIR)/$(LIBNAME).*
49+
rm -rf fuzz_harness $(OBJS) $(BINARY) $(BINARYBIN) $(OBJDIR)/lib$(LIBNAME).* $(OBJDIR)/$(LIBNAME).*
4950

5051
$(BINARY): fuzz_disasm.o drivermc.o
5152
@mkdir -p $(@D)
@@ -56,6 +57,15 @@ else
5657
$(link-static)
5758
endif
5859

60+
$(BINARYBIN): fuzz_disasm.o driverbin.o
61+
@mkdir -p $(@D)
62+
ifeq ($(V),0)
63+
$(call log,LINK,$(notdir $@))
64+
@$(link-static)
65+
else
66+
$(link-static)
67+
endif
68+
5969
$(OBJDIR)/%.o: %.c
6070
@mkdir -p $(@D)
6171
ifeq ($(V),0)

suite/fuzz/driverbin.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#include <stdint.h>
2+
#include <stdlib.h>
3+
#include <stdio.h>
4+
#include <dirent.h>
5+
#include <unistd.h>
6+
7+
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
8+
9+
int main(int argc, char** argv)
10+
{
11+
FILE * fp;
12+
uint8_t Data[0x1000];
13+
size_t Size;
14+
DIR *d;
15+
struct dirent *dir;
16+
int r = 0;
17+
18+
if (argc != 2) {
19+
return 1;
20+
}
21+
22+
d = opendir(argv[1]);
23+
if (d == NULL) {
24+
printf("Invalid directory\n");
25+
return 2;
26+
}
27+
if (chdir(argv[1]) != 0) {
28+
closedir(d);
29+
printf("Invalid directory\n");
30+
return 2;
31+
}
32+
33+
while((dir = readdir(d)) != NULL) {
34+
//opens the file, get its size, and reads it into a buffer
35+
if (dir->d_type != DT_REG) {
36+
continue;
37+
}
38+
//printf("Running %s\n", dir->d_name);
39+
fp = fopen(dir->d_name, "rb");
40+
if (fp == NULL) {
41+
r = 3;
42+
break;
43+
}
44+
if (fseek(fp, 0L, SEEK_END) != 0) {
45+
fclose(fp);
46+
r = 4;
47+
break;
48+
}
49+
Size = ftell(fp);
50+
if (Size == (size_t) -1) {
51+
fclose(fp);
52+
r = 5;
53+
break;
54+
} else if (Size > 0x1000) {
55+
fclose(fp);
56+
continue;
57+
}
58+
if (fseek(fp, 0L, SEEK_SET) != 0) {
59+
fclose(fp);
60+
r = 7;
61+
break;
62+
}
63+
if (fread(Data, Size, 1, fp) != 1) {
64+
fclose(fp);
65+
r = 8;
66+
break;
67+
}
68+
69+
//lauch fuzzer
70+
LLVMFuzzerTestOneInput(Data, Size);
71+
fclose(fp);
72+
}
73+
closedir(d);
74+
return r;
75+
}
76+

suite/fuzz/fuzz_diff.c

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
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+
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+
}

0 commit comments

Comments
 (0)