Merge commit '802798ce3c8baa4697120580f87bc1ee377306d3' as 'external/capstone'

This commit is contained in:
2026-05-11 11:55:07 +02:00
3968 changed files with 2967598 additions and 0 deletions
+120
View File
@@ -0,0 +1,120 @@
# Capstone Disassembler Engine
# By Philippe Antoine <contact@catenacyber.fr>, 2018
include ../../config.mk
include ../../functions.mk
ifneq ($(CAPSTONE_STATIC),yes)
$(error Needs static capstone.)
endif
# Verbose output?
V ?= 0
INCDIR = ../../include
ifndef BUILDDIR
TESTDIR = .
OBJDIR = .
LIBDIR = ../..
else
TESTDIR = $(BUILDDIR)/tests
OBJDIR = $(BUILDDIR)/obj/tests
LIBDIR = $(BUILDDIR)
endif
CFLAGS += -Wall -I$(INCDIR)
LDFLAGS += -L$(LIBDIR)
CFLAGS += $(foreach arch,$(LIBARCHS),-arch $(arch))
LDFLAGS += $(foreach arch,$(LIBARCHS),-arch $(arch))
FUZZLDFLAGS =
LIBNAME = capstone
IS_CYGWIN := $(shell $(CC) -dumpmachine 2>/dev/null | grep -i cygwin | wc -l)
ifeq ($(IS_CYGWIN),1)
EXT = dll
AR_EXT = lib
ARCHIVE = $(LIBDIR)/$(LIBNAME).$(AR_EXT)
else
BIN_EXT =
AR_EXT = a
ARCHIVE = $(LIBDIR)/lib$(LIBNAME).$(AR_EXT)
endif
ARCHIVE = $(LIBDIR)/lib$(LIBNAME).$(AR_EXT)
.PHONY: all clean
SOURCES = fuzz_disasm.c drivermc.c fuzz_harness.c driverbin.c platform.c
OBJS = $(addprefix $(OBJDIR)/,$(SOURCES:.c=.o))
# reproducer using MC file as input
REPRODUCERMC = $(addprefix $(TESTDIR)/,fuzz_disasm$(BIN_EXT))
# reproducer using raw binary file as input (as produced by fuzzer)
REPRODUCERBIN = $(addprefix $(TESTDIR)/,fuzz_bindisasm$(BIN_EXT))
# fuzzer
FUZZERBIN = $(addprefix $(TESTDIR)/,fuzz_bindisasm2$(BIN_EXT))
PLATFORMDECODE = $(addprefix $(TESTDIR)/,fuzz_decode_platform$(BIN_EXT))
all: $(REPRODUCERMC) $(REPRODUCERBIN) $(FUZZERBIN) $(PLATFORMDECODE)
clean:
rm -rf fuzz_harness $(OBJS) $(PLATFORMDECODE) $(REPRODUCERMC) $(REPRODUCERBIN) $(FUZZERBIN) $(OBJDIR)/lib$(LIBNAME).* $(OBJDIR)/$(LIBNAME).*
rm -f *.d $(OBJDIR)/*.d
$(REPRODUCERMC): fuzz_disasm.o drivermc.o platform.o
@mkdir -p $(@D)
ifeq ($(V),0)
$(call log,LINK,$(notdir $@))
@$(link-static)
else
$(link-static)
endif
$(REPRODUCERBIN): fuzz_disasm.o driverbin.o platform.o
@mkdir -p $(@D)
ifeq ($(V),0)
$(call log,LINK,$(notdir $@))
@$(link-static)
else
$(link-static)
endif
$(FUZZERBIN): FUZZLDFLAGS="-fsanitize=fuzzer -fno-sanitize-coverage=stack-depth"
$(FUZZERBIN): fuzz_disasm.o platform.o
@mkdir -p $(@D)
ifeq ($(V),0)
$(call log,LINK,$(notdir $@))
@$(link-static) || touch $(FUZZERBIN)
else
$(link-static) || touch $(FUZZERBIN)
endif
$(PLATFORMDECODE): fuzz_decode_platform.o platform.o
@mkdir -p $(@D)
ifeq ($(V),0)
$(call log,LINK,$(notdir $@))
@$(link-static)
else
$(link-static)
endif
$(OBJDIR)/%.o: %.c
@mkdir -p $(@D)
ifeq ($(V),0)
$(call log,CC,$(@:$(OBJDIR)/%=%))
@$(compile)
else
$(compile)
endif
define link-static
$(CC) $(LDFLAGS) $(FUZZLDFLAGS) $^ $(ARCHIVE) -o $@
endef
fuzz_harness: fuzz_harness.o
${CC} $< -O3 -Wall -l$(LIBNAME) -o $@
+73
View File
@@ -0,0 +1,73 @@
Fuzzing
===============
Build the fuzz target
-------
To build the fuzz target, you can simply run `make` with appropriate flags set :
```
ASAN_OPTIONS=detect_leaks=0 CXXFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address -fsanitize=fuzzer-no-link" CFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address -fsanitize=fuzzer-no-link" LDFLAGS="-fsanitize=address" make
```
You can replace `address` with another sanitizer : `memory` or `undefined`
The fuzz target is then `suite/fuzz/fuzz_bindisasm2`
You can find this in travis configuration `.travis.yml`
Another way is to use oss-fuzz, see https://github.com/google/oss-fuzz/blob/master/projects/capstone/build.sh
Troubleshooting
------
If you get `cc: error: unrecognized argument to -fsanitize= option: fuzzer` check if you have a workable
version of `libfuzz` installed. Also try to build with `CC=clang make`
Interpret OSS-Fuzz report
------
A reported bug by OSS-fuzz looks usually like this:
```
...
#20 0x7f3a42062082 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x24082) (BuildId: 0702430aef5fa3dda43986563e9ffcc47efbd75e)
#21 0x55ad814876dd in _start (build-out/fuzz_disasmnext+0x5246dd)
DEDUP_TOKEN: raise--abort--
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: ABRT (/lib/x86_64-linux-gnu/libc.so.6+0x4300b) (BuildId: 0702430aef5fa3dda43986563e9ffcc47efbd75e) in raise
==62==ABORTING
MS: 0 ; base unit: 0000000000000000000000000000000000000000
0x7,0xe8,0x3,0x4e,0xc0,0xf8,
\007\350\003N\300\370
```
It emits the bytes fed to Capstone in the last two lines.
The first byte determines the `arch+mode`. The following bytes the actual data producing the crash.
You can run `./fuzz_decode_platform` to get the `arch+mode` used:
```
./fuzz_decode_platform 0x7
cstool arch+mode = aarch64
```
And reproduce the bug with `cstool`:
```bash
# Make sureevery hex number has two digits!
cstool -d aarch64 0xe8,0x03,0x4e,0xc0,0xf8,
```
Make sure the every hex number has two digits (`0x3 -> 0x03`)!
`cstool` won't parse it correctly otherwise.
Fuzz drivers
------
There are custom drivers :
- driverbin.c : prints cstool command before running one input
- drivermc.c : converts MC test data to raw binary data before running as many inputs as there are lines in a file
- onefile.c : simple one file driver
For libfuzzer, the preferred main function is now to use linker option `-fsanitize=fuzzer`
+88
View File
@@ -0,0 +1,88 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <dirent.h>
#include <unistd.h>
#include "platform.h"
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
int main(int argc, char **argv)
{
FILE *fp;
uint8_t Data[0x1000];
size_t Size;
DIR *d;
struct dirent *dir;
int r = 0;
int i;
if (argc != 2) {
return 1;
}
d = opendir(argv[1]);
if (d == NULL) {
printf("Invalid directory\n");
return 2;
}
if (chdir(argv[1]) != 0) {
closedir(d);
printf("Invalid directory\n");
return 2;
}
while ((dir = readdir(d)) != NULL) {
//opens the file, get its size, and reads it into a buffer
if (dir->d_type != DT_REG) {
continue;
}
printf("Running file %s ", dir->d_name);
fflush(stdout);
fp = fopen(dir->d_name, "rb");
if (fp == NULL) {
r = 3;
break;
}
if (fseek(fp, 0L, SEEK_END) != 0) {
fclose(fp);
r = 4;
break;
}
Size = ftell(fp);
if (Size == (size_t)-1) {
fclose(fp);
r = 5;
break;
} else if (Size > 0x1000) {
fclose(fp);
continue;
}
if (fseek(fp, 0L, SEEK_SET) != 0) {
fclose(fp);
r = 7;
break;
}
if (fread(Data, Size, 1, fp) != 1) {
fclose(fp);
r = 8;
break;
}
if (Size > 0) {
printf("command cstool %s\n",
get_platform_cstoolname(Data[0]));
}
for (i = 0; i < Size; i++) {
printf("%02x", Data[i]);
}
printf("\n");
//launch fuzzer
LLVMFuzzerTestOneInput(Data, Size);
fclose(fp);
}
closedir(d);
printf("Ok : whole directory finished\n");
return r;
}
+204
View File
@@ -0,0 +1,204 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
#define MAX_INSTR_SIZE 64
#define MAX_LINE_SIZE 128
int main(int argc, char **argv)
{
FILE *fp;
uint8_t Data[MAX_INSTR_SIZE];
char line[MAX_LINE_SIZE];
size_t Size;
char arch[MAX_LINE_SIZE];
char mode[MAX_LINE_SIZE];
unsigned int value;
int i;
if (argc < 2) {
return 1;
}
for (i = 1; i < argc; i++) {
//opens the file, get its size, and reads it into a buffer
fp = fopen(argv[i], "rb");
if (fp == NULL) {
return 2;
}
printf("Trying %s\n", argv[i]);
if (fgets(line, MAX_LINE_SIZE, fp) == NULL) {
break;
}
if (line[0] == '#') {
if (sscanf(line, "# %[^,], %[^,]", arch, mode) != 2) {
printf("Wrong mode %s\n", line);
return 1;
}
if (strcmp(arch, "CS_ARCH_X86") == 0 &&
strcmp(mode, "CS_MODE_32") == 0) {
Data[0] = 0;
} else if (strcmp(arch, "CS_ARCH_X86") == 0 &&
strcmp(mode, "CS_MODE_64") == 0) {
Data[0] = 1;
} else if (strcmp(arch, "CS_ARCH_ARM") == 0 &&
strcmp(mode, "CS_MODE_ARM") == 0) {
Data[0] = 2;
} else if (strcmp(arch, "CS_ARCH_ARM") == 0 &&
strcmp(mode, "CS_MODE_THUMB") == 0) {
Data[0] = 3;
} else if (strcmp(arch, "CS_ARCH_ARM") == 0 &&
strcmp(mode, "CS_MODE_ARM+CS_MODE_V8") ==
0) {
Data[0] = 4;
} else if (strcmp(arch, "CS_ARCH_ARM") == 0 &&
strcmp(mode, "CS_MODE_THUMB+CS_MODE_V8") ==
0) {
Data[0] = 5;
} else if (strcmp(arch, "CS_ARCH_ARM") == 0 &&
strcmp(mode,
"CS_MODE_THUMB+CS_MODE_MCLASS") ==
0) {
Data[0] = 6;
} else if (strcmp(arch, "CS_ARCH_ARM64") == 0 &&
strcmp(mode, "0") == 0) {
Data[0] = 7;
} else if (strcmp(arch, "CS_ARCH_MIPS") == 0 &&
strcmp(mode,
"CS_MODE_MIPS32+CS_MODE_BIG_ENDIAN") ==
0) {
Data[0] = 8;
} else if (strcmp(arch, "CS_ARCH_MIPS") == 0 &&
strcmp(mode,
"CS_MODE_MIPS32+CS_MODE_MICRO") ==
0) {
Data[0] = 9;
} else if (strcmp(arch, "CS_ARCH_MIPS") == 0 &&
strcmp(mode, "CS_MODE_MIPS64") == 0) {
Data[0] = 10;
} else if (strcmp(arch, "CS_ARCH_MIPS") == 0 &&
strcmp(mode, "CS_MODE_MIPS32") == 0) {
Data[0] = 11;
} else if (strcmp(arch, "CS_ARCH_MIPS") == 0 &&
strcmp(mode,
"CS_MODE_MIPS64+CS_MODE_BIG_ENDIAN") ==
0) {
Data[0] = 12;
} else if (strcmp(arch, "CS_ARCH_MIPS") == 0 &&
strcmp(mode,
"CS_MODE_MIPS32+CS_MODE_MICRO+CS_MODE_BIG_ENDIAN") ==
0) {
Data[0] = 13;
} else if (strcmp(arch, "CS_ARCH_MIPS") == 0 &&
strcmp(mode,
"CS_MODE_MIPS32+CS_MODE_BIG_ENDIAN+CS_MODE_MICRO") ==
0) {
Data[0] = 13;
} else if (strcmp(arch, "CS_ARCH_PPC") == 0 &&
strcmp(mode, "CS_MODE_BIG_ENDIAN") == 0) {
Data[0] = 14;
} else if (strcmp(arch, "CS_ARCH_SPARC") == 0 &&
strcmp(mode, "CS_MODE_BIG_ENDIAN") == 0) {
Data[0] = 15;
} else if (strcmp(arch, "CS_ARCH_SPARC") == 0 &&
strcmp(mode,
"CS_MODE_BIG_ENDIAN + CS_MODE_V9") ==
0) {
Data[0] = 16;
} else if (strcmp(arch, "CS_ARCH_SYSTEMZ") == 0 &&
strcmp(mode, "0") == 0) {
Data[0] = 17;
} else if (strcmp(arch, "CS_ARCH_XCORE") == 0 &&
strcmp(mode, "0") == 0) {
Data[0] = 18;
} else if (strcmp(arch, "CS_ARCH_MIPS") == 0 &&
strcmp(mode,
"CS_MODE_MIPS32R6+CS_MODE_BIG_ENDIAN") ==
0) {
Data[0] = 19;
} else if (strcmp(arch, "CS_ARCH_MIPS") == 0 &&
strcmp(mode,
"CS_MODE_MIPS32R6+CS_MODE_MICRO+CS_MODE_BIG_ENDIAN") ==
0) {
Data[0] = 20;
} else if (strcmp(arch, "CS_ARCH_MIPS") == 0 &&
strcmp(mode, "CS_MODE_MIPS32R6") == 0) {
Data[0] = 21;
} else if (strcmp(arch, "CS_ARCH_MIPS") == 0 &&
strcmp(mode,
"CS_MODE_MIPS32R6+CS_MODE_MICRO") ==
0) {
Data[0] = 22;
} else if (strcmp(arch, "CS_ARCH_M68K") == 0 &&
strcmp(mode, "0") == 0) {
Data[0] = 23;
} else if (strcmp(arch, "CS_ARCH_M680X") == 0 &&
strcmp(mode, "CS_MODE_M680X_6809") == 0) {
Data[0] = 24;
} else if (strcmp(arch, "CS_ARCH_EVM") == 0 &&
strcmp(mode, "0") == 0) {
Data[0] = 25;
} else if (strcmp(arch, "CS_ARCH_XTENSA") == 0 &&
strcmp(mode, "CS_MODE_XTENSA_ESP32") == 0) {
Data[0] = 26;
} else if (strcmp(arch, "CS_ARCH_XTENSA") == 0 &&
strcmp(mode, "CS_MODE_XTENSA_ESP32S2") ==
0) {
Data[0] = 27;
} else if (strcmp(arch, "CS_ARCH_XTENSA") == 0 &&
strcmp(mode, "CS_MODE_XTENSA_ESP8266") ==
0) {
Data[0] = 28;
} else if (strcmp(arch, "CS_ARCH_BPF") == 0 &&
strstr(mode, "CS_MODE_BPF_CLASSIC") !=
NULL) {
Data[0] = 29;
} else if (strcmp(arch, "CS_ARCH_BPF") == 0 &&
strstr(mode, "CS_MODE_BPF_EXTENDED") !=
NULL) {
Data[0] = 30;
} else if (strcmp(arch, "CS_ARCH_RISCV") == 0 &&
strcmp(mode, "CS_MODE_RISCV32") == 0) {
Data[0] = 44;
} else if (strcmp(arch, "CS_ARCH_RISCV") == 0 &&
strcmp(mode, "CS_MODE_RISCV64") == 0) {
Data[0] = 45;
} else {
printf("Unknown mode\n");
//fail instead of continue
return 1;
}
} else {
printf("No mode\n");
//fail instead of continue
return 1;
}
while (1) {
if (fgets(line, MAX_LINE_SIZE, fp) == NULL) {
break;
}
Size = 1;
// we start line at offset 0 and Data buffer at offset 1
// since Data[0] is option : arch + mode
while (sscanf(line + (Size - 1) * 5, "0x%02x",
&value) == 1) {
Data[Size] = value;
Size++;
if (line[(Size - 1) * 5 - 1] != ',') {
//end of pattern
break;
} else if (MAX_LINE_SIZE < (Size - 1) * 5) {
printf("Line overflow\n");
return 1;
}
}
//launch fuzzer
LLVMFuzzerTestOneInput(Data, Size);
}
fclose(fp);
}
return 0;
}
+26
View File
@@ -0,0 +1,26 @@
// this tool decodes first input byte feed to OSS fuzz, that encodes arch+mode
// by Nguyen Anh Quynh, 2019
#include <stdio.h>
#include <inttypes.h>
#include <capstone/capstone.h>
#include "platform.h"
int main(int argc, char **argv)
{
unsigned char data;
if (argc != 2) {
printf("Decoding OSS fuzz platform\n");
printf("Syntax: %s <hex-byte>\n", argv[0]);
return -1;
}
data = (unsigned int)strtol(argv[1], NULL, 16);
printf("cstool arch+mode = %s\n", get_platform_cstoolname(data));
return 0;
}
+154
View File
@@ -0,0 +1,154 @@
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <assert.h>
#include <capstone/capstone.h>
struct platform {
cs_arch arch;
cs_mode mode;
char *comment;
};
FILE *outfile = NULL;
struct platform platforms[] = {
{ // item 0
CS_ARCH_X86, CS_MODE_32, "X86 32 (Intel syntax)" },
{ // item 1
CS_ARCH_X86, CS_MODE_64, "X86 64 (Intel syntax)" },
{ // item 2
CS_ARCH_ARM, CS_MODE_ARM, "ARM" },
{ // item 3
CS_ARCH_ARM, CS_MODE_THUMB, "THUMB" },
{ // item 4
CS_ARCH_ARM, (cs_mode)(CS_MODE_ARM + CS_MODE_V8), "Arm-V8" },
{ // item 5
CS_ARCH_ARM, (cs_mode)(CS_MODE_THUMB + CS_MODE_V8), "THUMB+V8" },
{ // item 6
CS_ARCH_ARM, (cs_mode)(CS_MODE_THUMB + CS_MODE_MCLASS),
"Thumb-MClass" },
{ // item 7
CS_ARCH_ARM64, (cs_mode)0, "ARM-64" },
{ // item 8
CS_ARCH_MIPS, (cs_mode)(CS_MODE_MIPS32 + CS_MODE_BIG_ENDIAN),
"MIPS-32 (Big-endian)" },
{ // item 9
CS_ARCH_MIPS, (cs_mode)(CS_MODE_MIPS32 + CS_MODE_MICRO),
"MIPS-32 (micro)" },
{ //item 10
CS_ARCH_MIPS, CS_MODE_MIPS64, "MIPS-64-EL (Little-endian)" },
{ //item 11
CS_ARCH_MIPS, CS_MODE_MIPS32, "MIPS-32-EL (Little-endian)" },
{ //item 12
CS_ARCH_MIPS, (cs_mode)(CS_MODE_MIPS64 + CS_MODE_BIG_ENDIAN),
"MIPS-64 (Big-endian)" },
{ //item 13
CS_ARCH_MIPS,
(cs_mode)(CS_MODE_MIPS32 + CS_MODE_MICRO + CS_MODE_BIG_ENDIAN),
"MIPS-32 | Micro (Big-endian)" },
{ //item 14
CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, "PPC-64" },
{ //item 15
CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN, "Sparc" },
{ //item 16
CS_ARCH_SPARC, (cs_mode)(CS_MODE_BIG_ENDIAN + CS_MODE_V9),
"SparcV9" },
{ //item 17
CS_ARCH_SYSTEMZ, (cs_mode)0, "SystemZ" },
{ //item 18
CS_ARCH_XCORE, (cs_mode)0, "XCore" },
{ //item 19
CS_ARCH_MIPS, (cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_BIG_ENDIAN),
"MIPS-32R6 (Big-endian)" },
{ //item 20
CS_ARCH_MIPS,
(cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_MICRO + CS_MODE_BIG_ENDIAN),
"MIPS-32R6 (Micro+Big-endian)" },
{ //item 21
CS_ARCH_MIPS, CS_MODE_MIPS32R6, "MIPS-32R6 (Little-endian)" },
{ //item 22
CS_ARCH_MIPS, (cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_MICRO),
"MIPS-32R6 (Micro+Little-endian)" },
{ //item 23
CS_ARCH_M68K, (cs_mode)0, "M68K" },
{ //item 24
CS_ARCH_M680X, (cs_mode)CS_MODE_M680X_6809, "M680X_M6809" },
{ //item 25
CS_ARCH_EVM, (cs_mode)0, "EVM" },
{ //item 26
CS_ARCH_XTENSA, (cs_mode)CS_MODE_XTENSA_ESP32, "Xtensa ESP32" },
{ //item 27
CS_ARCH_XTENSA, (cs_mode)CS_MODE_XTENSA_ESP32S2, "Xtensa ESP32S2" },
{ //item 28
CS_ARCH_XTENSA, (cs_mode)CS_MODE_XTENSA_ESP8266, "Xtensa ESP8266" },
};
void LLVMFuzzerInit();
int LLVMFuzzerReturnOneInput(const uint8_t *Data, size_t Size,
char *AssemblyText);
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
{
csh handle;
cs_insn *insn;
cs_err err;
const uint8_t **Datap = &Data;
size_t *Sizep = &Size;
uint64_t address = 0x1000;
char LLVMAssemblyText[80];
char CapstoneAssemblyText[80];
if (Size < 1) {
// 1 byte for arch choice
return 0;
} else if (Size > 0x1000) {
//limit input to 4kb
Size = 0x1000;
}
if (outfile == NULL) {
// we compute the output
outfile = fopen("/dev/null", "w");
if (outfile == NULL) {
return 0;
}
LLVMFuzzerInit();
}
if (Data[0] >= sizeof(platforms) / sizeof(platforms[0])) {
return 0;
}
if (LLVMFuzzerReturnOneInput(Data, Size, LLVMAssemblyText) == 1) {
return 0;
}
err = cs_open(platforms[Data[0]].arch, platforms[Data[0]].mode,
&handle);
if (err) {
return 0;
}
insn = cs_malloc(handle);
Data++;
Size--;
assert(insn);
if (cs_disasm_iter(handle, Datap, Sizep, &address, insn)) {
snprintf(CapstoneAssemblyText, 80, "\t%s\t%s", insn->mnemonic,
insn->op_str);
if (strcmp(CapstoneAssemblyText, LLVMAssemblyText) != 0) {
printf("capstone %s != llvm %s", CapstoneAssemblyText,
LLVMAssemblyText);
abort();
}
} else {
printf("capstone failed with llvm %s", LLVMAssemblyText);
abort();
}
cs_free(insn, 1);
cs_close(&handle);
return 0;
}
+114
View File
@@ -0,0 +1,114 @@
// the following must precede stdio (woo, thanks msft)
#if defined(_MSC_VER) && _MSC_VER < 1900
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <capstone/capstone.h>
#include "platform.h"
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
static FILE *outfile = NULL;
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
{
csh handle;
cs_insn *all_insn;
cs_detail *detail;
cs_err err;
unsigned int i;
if (Size < 1) {
// 1 byte for arch choice
return 0;
} else if (Size > 0x1000) {
//limit input to 4kb
Size = 0x1000;
}
if (outfile == NULL) {
// we compute the output
outfile = fopen("/dev/null", "w");
if (outfile == NULL) {
return 0;
}
}
i = get_platform_entry((uint8_t)Data[0]);
err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
if (err) {
return 0;
}
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
if (Data[0] & 0x80) {
//hack
cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT);
}
uint64_t address = 0x1000;
size_t count =
cs_disasm(handle, Data + 1, Size - 1, address, 0, &all_insn);
if (count) {
size_t j;
unsigned int n;
for (j = 0; j < count; j++) {
cs_insn *insn = &(all_insn[j]);
fprintf(outfile,
"0x%" PRIx64
":\t%s\t\t%s // insn-ID: %u, insn-mnem: %s\n",
insn->address, insn->mnemonic, insn->op_str,
insn->id, cs_insn_name(handle, insn->id));
detail = insn->detail;
if (detail->regs_read_count > 0) {
fprintf(outfile, "\tImplicit registers read: ");
for (n = 0; n < detail->regs_read_count; n++) {
fprintf(outfile, "%s ",
cs_reg_name(
handle,
detail->regs_read[n]));
}
}
if (detail->regs_write_count > 0) {
fprintf(outfile,
"\tImplicit registers modified: ");
for (n = 0; n < detail->regs_write_count; n++) {
fprintf(outfile, "%s ",
cs_reg_name(
handle,
detail->regs_write[n]));
}
}
if (detail->groups_count > 0) {
fprintf(outfile,
"\tThis instruction belongs to groups: ");
for (n = 0; n < detail->groups_count; n++) {
fprintf(outfile, "%s ",
cs_group_name(
handle,
detail->groups[n]));
}
}
}
fprintf(outfile, "0x%" PRIx64 ":\n",
all_insn[j - 1].address + all_insn[j - 1].size);
cs_free(all_insn, count);
}
cs_close(&handle);
return 0;
}
+2
View File
@@ -0,0 +1,2 @@
[libfuzzer]
max_len = 4096
+176
View File
@@ -0,0 +1,176 @@
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <capstone.h>
struct platform {
cs_arch arch;
cs_mode mode;
char *comment;
};
int main(int argc, char **argv)
{
if (argc != 2) {
printf("Usage: %s <testcase>\n", argv[0]);
return 1;
}
struct platform platforms[] = {
{ CS_ARCH_X86, CS_MODE_32, "X86 32 (Intel syntax)" },
{ CS_ARCH_X86, CS_MODE_64, "X86 64 (Intel syntax)" },
{ CS_ARCH_ARM, CS_MODE_ARM, "ARM" },
{ CS_ARCH_ARM, CS_MODE_THUMB, "THUMB-2" },
{ CS_ARCH_ARM, CS_MODE_ARM, "ARM: Cortex-A15 + NEON" },
{ CS_ARCH_ARM, CS_MODE_THUMB, "THUMB" },
{ CS_ARCH_ARM, (cs_mode)(CS_MODE_THUMB + CS_MODE_MCLASS),
"Thumb-MClass" },
{ CS_ARCH_ARM, (cs_mode)(CS_MODE_ARM + CS_MODE_V8), "Arm-V8" },
{ CS_ARCH_MIPS, (cs_mode)(CS_MODE_MIPS32 + CS_MODE_BIG_ENDIAN),
"MIPS-32 (Big-endian)" },
{ CS_ARCH_MIPS,
(cs_mode)(CS_MODE_MIPS64 + CS_MODE_LITTLE_ENDIAN),
"MIPS-64-EL (Little-endian)" },
{ CS_ARCH_MIPS,
(cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_MICRO +
CS_MODE_BIG_ENDIAN),
"MIPS-32R6 | Micro (Big-endian)" },
{ CS_ARCH_MIPS,
(cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_BIG_ENDIAN),
"MIPS-32R6 (Big-endian)" },
{ CS_ARCH_ARM64, CS_MODE_ARM, "ARM-64" },
{ CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, "PPC-64" },
{ CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN, "Sparc" },
{ CS_ARCH_SPARC, (cs_mode)(CS_MODE_BIG_ENDIAN + CS_MODE_V9),
"SparcV9" },
{ CS_ARCH_SYSTEMZ, (cs_mode)0, "SystemZ" },
{ CS_ARCH_XCORE, (cs_mode)0, "XCore" },
{ CS_ARCH_M68K, (cs_mode)0, "M68K" },
{ CS_ARCH_M680X, (cs_mode)CS_MODE_M680X_6809, "M680X_M6809" },
{ CS_ARCH_XTENSA, (cs_mode)CS_MODE_XTENSA_ESP32,
"Xtensa ESP32" },
{ CS_ARCH_XTENSA, (cs_mode)CS_MODE_XTENSA_ESP32S2,
"Xtensa ESP32S2" },
{ CS_ARCH_XTENSA, (cs_mode)CS_MODE_XTENSA_ESP8266,
"Xtensa ESP8266" },
};
// Read input
long bufsize = 0;
unsigned char *buf = NULL;
FILE *fp = fopen(argv[1], "r");
if (fp == NULL)
return 1;
if (fseek(fp, 0L, SEEK_END) == 0) {
bufsize = ftell(fp);
if (bufsize == -1)
return 1;
buf = malloc(bufsize + 1);
if (buf == NULL)
return 1;
if (fseek(fp, 0L, SEEK_SET) != 0)
return 1;
size_t len = fread(buf, sizeof(char), bufsize, fp);
if (len == 0)
return 2;
}
fclose(fp);
// Disassemble
csh handle;
cs_insn *all_insn;
cs_detail *detail;
cs_err err;
if (bufsize < 3)
return 0;
int platforms_len = sizeof(platforms) / sizeof(platforms[0]);
int i = (int)buf[0] % platforms_len;
unsigned char *buf_ptr = buf + 1;
long buf_ptr_size = bufsize - 1;
printf("Platform: %s (0x%.2x of 0x%.2x)\n", platforms[i].comment, i,
platforms_len);
err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
if (err) {
printf("Failed on cs_open() with error returned: %u\n", err);
return 1;
}
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
uint64_t address = 0x1000;
size_t count =
cs_disasm(handle, buf_ptr, buf_ptr_size, address, 0, &all_insn);
if (count) {
size_t j;
int n;
printf("Disasm:\n");
for (j = 0; j < count; j++) {
cs_insn *i = &(all_insn[j]);
printf("0x%" PRIx64
":\t%s\t\t%s // insn-ID: %u, insn-mnem: %s\n",
i->address, i->mnemonic, i->op_str, i->id,
cs_insn_name(handle, i->id));
detail = i->detail;
if (detail->regs_read_count > 0) {
printf("\tImplicit registers read: ");
for (n = 0; n < detail->regs_read_count; n++) {
printf("%s ",
cs_reg_name(
handle,
detail->regs_read[n]));
}
printf("\n");
}
if (detail->regs_write_count > 0) {
printf("\tImplicit registers modified: ");
for (n = 0; n < detail->regs_write_count; n++) {
printf("%s ",
cs_reg_name(
handle,
detail->regs_write[n]));
}
printf("\n");
}
if (detail->groups_count > 0) {
printf("\tThis instruction belongs to groups: ");
for (n = 0; n < detail->groups_count; n++) {
printf("%s ",
cs_group_name(handle,
detail->groups[n]));
}
printf("\n");
}
}
printf("0x%" PRIx64 ":\n",
all_insn[j - 1].address + all_insn[j - 1].size);
cs_free(all_insn, count);
} else {
printf("ERROR: Failed to disasm given code!\n");
}
printf("\n");
free(buf);
cs_close(&handle);
return 0;
}
+41
View File
@@ -0,0 +1,41 @@
#include "llvm-c/Disassembler.h"
#include "llvm-c/Target.h"
#include "llvm/MC/SubtargetFeature.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
extern "C" void LLVMFuzzerInit() {
LLVMInitializeAllTargetInfos();
LLVMInitializeAllTargetMCs();
LLVMInitializeAllDisassemblers();
}
extern "C" int LLVMFuzzerReturnOneInput(const uint8_t *Data, size_t Size, char * AssemblyText) {
LLVMDisasmContextRef Ctx;
std::vector<uint8_t> DataCopy(Data, Data + Size);
uint8_t *p = DataCopy.data();
int r = 1;
switch(Data[0]) {
case 0:
Ctx = LLVMCreateDisasmCPUFeatures("i386", "", "", nullptr, 0, nullptr, nullptr);
if (LLVMSetDisasmOptions(Ctx, LLVMDisassembler_Option_AsmPrinterVariant) == 0) {
abort();
}
break;
//TODO other cases
default:
return 1;
}
assert(Ctx);
if (LLVMDisasmInstruction(Ctx, p+1, Size-1, 0, AssemblyText, 80) > 0) {
r = 0;
}
LLVMDisasmDispose(Ctx);
return r;
}
+50
View File
@@ -0,0 +1,50 @@
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
int main(int argc, char **argv)
{
FILE *fp;
uint8_t *Data;
size_t Size;
if (argc != 2) {
return 1;
}
//opens the file, get its size, and reads it into a buffer
fp = fopen(argv[1], "rb");
if (fp == NULL) {
return 2;
}
if (fseek(fp, 0L, SEEK_END) != 0) {
fclose(fp);
return 2;
}
Size = ftell(fp);
if (Size == (size_t)-1) {
fclose(fp);
return 2;
}
if (fseek(fp, 0L, SEEK_SET) != 0) {
fclose(fp);
return 2;
}
Data = malloc(Size);
if (Data == NULL) {
fclose(fp);
return 2;
}
if (fread(Data, Size, 1, fp) != 1) {
fclose(fp);
free(Data);
return 2;
}
//launch fuzzer
LLVMFuzzerTestOneInput(Data, Size);
free(Data);
fclose(fp);
return 0;
}
+185
View File
@@ -0,0 +1,185 @@
#include "platform.h"
struct platform platforms[] = {
{ // item 0
CS_ARCH_X86, CS_MODE_32, "X86 32 (Intel syntax)", "x32" },
{ // item 1
CS_ARCH_X86, CS_MODE_64, "X86 64 (Intel syntax)", "x64" },
{ // item 2
CS_ARCH_ARM, CS_MODE_ARM, "ARM", "arm" },
{ // item 3
CS_ARCH_ARM, CS_MODE_THUMB, "THUMB", "thumb" },
{ // item 4
CS_ARCH_ARM, (cs_mode)(CS_MODE_ARM + CS_MODE_V8), "Arm-V8", "armv8" },
{ // item 5
CS_ARCH_ARM, (cs_mode)(CS_MODE_THUMB + CS_MODE_V8), "THUMB+V8",
"thumbv8" },
{ // item 6
CS_ARCH_ARM, (cs_mode)(CS_MODE_THUMB + CS_MODE_MCLASS),
"Thumb-MClass", "cortexm" },
{ // item 7
CS_ARCH_AARCH64, (cs_mode)0, "AARCH64", "aarch64" },
{ // item 8
CS_ARCH_MIPS, (cs_mode)(CS_MODE_MIPS32 + CS_MODE_BIG_ENDIAN),
"MIPS-32 (Big-endian)", "mipsbe" },
{ // item 9
CS_ARCH_MIPS, (cs_mode)(CS_MODE_MIPS32 + CS_MODE_MICRO),
"MIPS-32 (micro)", "mipsmicro" },
{ //item 10
CS_ARCH_MIPS, CS_MODE_MIPS64, "MIPS-64-EL (Little-endian)",
"mips64" },
{ //item 11
CS_ARCH_MIPS, CS_MODE_MIPS32, "MIPS-32-EL (Little-endian)", "mips" },
{ //item 12
CS_ARCH_MIPS, (cs_mode)(CS_MODE_MIPS64 + CS_MODE_BIG_ENDIAN),
"MIPS-64 (Big-endian)", "mips64be" },
{ //item 13
CS_ARCH_MIPS,
(cs_mode)(CS_MODE_MIPS32 + CS_MODE_MICRO + CS_MODE_BIG_ENDIAN),
"MIPS-32 | Micro (Big-endian)", "mipsbemicro" },
{ //item 14
CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN, "PPC-64", "ppc64be" },
{ //item 15
CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN, "Sparc", "sparc" },
{ //item 16
CS_ARCH_SPARC, (cs_mode)(CS_MODE_BIG_ENDIAN + CS_MODE_V9), "SparcV9",
"sparcv9" },
{ //item 17
CS_ARCH_SYSTEMZ, (cs_mode)CS_MODE_BIG_ENDIAN, "SystemZ", "systemz" },
{ //item 18
CS_ARCH_XCORE, (cs_mode)0, "XCore", "xcore" },
{ //item 19
CS_ARCH_MIPS, (cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_BIG_ENDIAN),
"MIPS-32R6 (Big-endian)", "mipsbe32r6" },
{ //item 20
CS_ARCH_MIPS,
(cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_MICRO + CS_MODE_BIG_ENDIAN),
"MIPS-32R6 (Micro+Big-endian)", "mipsbe32r6micro" },
{ //item 21
CS_ARCH_MIPS, CS_MODE_MIPS32R6, "MIPS-32R6 (Little-endian)",
"mips32r6" },
{ //item 22
CS_ARCH_MIPS, (cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_MICRO),
"MIPS-32R6 (Micro+Little-endian)", "mips32r6micro" },
{ //item 23
CS_ARCH_M68K, (cs_mode)0, "M68K", "m68k" },
{ //item 24
CS_ARCH_M680X, (cs_mode)CS_MODE_M680X_6809, "M680X_M6809", "m6809" },
{ //item 25
CS_ARCH_EVM, (cs_mode)0, "EVM", "evm" },
{ //item 26
CS_ARCH_MOS65XX, (cs_mode)0, "MOS65XX", "mos65xx" },
{ //item 27
CS_ARCH_TMS320C64X, CS_MODE_BIG_ENDIAN, "tms320c64x", "tms320c64x" },
{ //item 28
CS_ARCH_WASM, (cs_mode)0, "WASM", "wasm" },
{ //item 29
CS_ARCH_BPF, CS_MODE_LITTLE_ENDIAN | CS_MODE_BPF_CLASSIC, "cBPF",
"bpf" },
{ //item 30
CS_ARCH_BPF, CS_MODE_LITTLE_ENDIAN | CS_MODE_BPF_EXTENDED, "eBPF",
"ebpf" },
{ //item 31
CS_ARCH_BPF, CS_MODE_BIG_ENDIAN | CS_MODE_BPF_CLASSIC, "cBPF",
"bpfbe" },
{ //item 32
CS_ARCH_BPF, CS_MODE_BIG_ENDIAN | CS_MODE_BPF_EXTENDED, "eBPF",
"ebpfbe" },
{ // item 33
CS_ARCH_X86, CS_MODE_16, "X86 16 (Intel syntax)", "x16" },
{ // item 34
CS_ARCH_M68K, CS_MODE_M68K_040, "M68K mode 40", "m68k40" },
{ //item 35
CS_ARCH_M680X, (cs_mode)CS_MODE_M680X_6800, "M680X_M6800", "m6800" },
{ //item 36
CS_ARCH_M680X, (cs_mode)CS_MODE_M680X_6801, "M680X_M6801", "m6801" },
{ //item 37
CS_ARCH_M680X, (cs_mode)CS_MODE_M680X_6805, "M680X_M6805", "m6805" },
{ //item 38
CS_ARCH_M680X, (cs_mode)CS_MODE_M680X_6808, "M680X_M6808", "m6808" },
{ //item 39
CS_ARCH_M680X, (cs_mode)CS_MODE_M680X_6811, "M680X_M6811", "m6811" },
{ //item 40
CS_ARCH_M680X, (cs_mode)CS_MODE_M680X_CPU12, "M680X_cpu12", "cpu12" },
{ //item 41
CS_ARCH_M680X, (cs_mode)CS_MODE_M680X_6301, "M680X_M6808", "hd6301" },
{ //item 42
CS_ARCH_M680X, (cs_mode)CS_MODE_M680X_6309, "M680X_M6808", "hd6309" },
{ //item 43
CS_ARCH_M680X, (cs_mode)CS_MODE_M680X_HCS08, "M680X_M6808", "hcs08" },
{ CS_ARCH_M680X, (cs_mode)CS_MODE_M680X_RS08, "M680X_RS08", "rs08" },
{ CS_ARCH_M680X, (cs_mode)CS_MODE_M680X_HCS12X, "M680X_HCS12X",
"hcs12x" },
{ //item 44
CS_ARCH_RISCV, CS_MODE_RISCV32, "RISCV", "riscv32" },
{ //item 45
CS_ARCH_RISCV, CS_MODE_RISCV64, "RISCV", "riscv64" },
{ //item 46
CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN | CS_MODE_QPX, "ppc+qpx",
"ppc64beqpx" },
{ //item 46
CS_ARCH_PPC, CS_MODE_32 | CS_MODE_BIG_ENDIAN | CS_MODE_PS, "ppc+ps",
"ppc32beps" },
{ CS_ARCH_TRICORE,
CS_MODE_32 | CS_MODE_BIG_ENDIAN | CS_MODE_TRICORE_110, "TRICORE",
"tc110" },
{ CS_ARCH_TRICORE,
CS_MODE_32 | CS_MODE_BIG_ENDIAN | CS_MODE_TRICORE_120, "TRICORE",
"tc120" },
{ CS_ARCH_TRICORE,
CS_MODE_32 | CS_MODE_BIG_ENDIAN | CS_MODE_TRICORE_130, "TRICORE",
"tc130" },
{ CS_ARCH_TRICORE,
CS_MODE_32 | CS_MODE_BIG_ENDIAN | CS_MODE_TRICORE_131, "TRICORE",
"tc131" },
{ CS_ARCH_TRICORE,
CS_MODE_32 | CS_MODE_BIG_ENDIAN | CS_MODE_TRICORE_160, "TRICORE",
"tc160" },
{ CS_ARCH_TRICORE,
CS_MODE_32 | CS_MODE_BIG_ENDIAN | CS_MODE_TRICORE_161, "TRICORE",
"tc161" },
{ CS_ARCH_TRICORE,
CS_MODE_32 | CS_MODE_BIG_ENDIAN | CS_MODE_TRICORE_162, "TRICORE",
"tc162" },
{ CS_ARCH_TRICORE,
CS_MODE_32 | CS_MODE_BIG_ENDIAN | CS_MODE_TRICORE_180, "TRICORE",
"tc180" },
{ CS_ARCH_XTENSA, CS_MODE_XTENSA_ESP32, "XTENSA ESP32", "esp32" },
{ CS_ARCH_XTENSA, CS_MODE_XTENSA_ESP32S2, "XTENSA ESP32S2", "esp32s2" },
{ CS_ARCH_XTENSA, CS_MODE_XTENSA_ESP8266, "XTENSA ESP8266", "esp8266" },
// dummy entry to mark the end of this array.
// DO NOT DELETE THIS
{
0,
0,
NULL,
NULL,
},
};
// get length of platforms[]
unsigned int platform_len(void)
{
unsigned int c;
for (c = 0; platforms[c].cstoolname; c++)
;
return c;
}
// get platform entry encoded n (first byte for input data of OSS fuzz)
unsigned int get_platform_entry(uint8_t n)
{
unsigned len = platform_len();
if (len == 0) {
return 0;
}
return n % len;
}
// get cstoolname from encoded n (first byte for input data of OSS fuzz)
const char *get_platform_cstoolname(uint8_t n)
{
return platforms[get_platform_entry(n)].cstoolname;
}
+24
View File
@@ -0,0 +1,24 @@
#ifndef CS_FUZZ_PLATFORM_H
#define CS_FUZZ_PLATFORM_H
#include <capstone/capstone.h>
struct platform {
cs_arch arch;
cs_mode mode;
const char *comment;
const char *cstoolname;
};
extern struct platform platforms[];
// get length of platforms[]
unsigned int platform_len(void);
// get platform entry encoded n (first byte for input data of OSS fuzz)
unsigned int get_platform_entry(uint8_t n);
// get cstoolname from encoded n (first byte for input data of OSS fuzz)
const char *get_platform_cstoolname(uint8_t n);
#endif