aboutsummaryrefslogtreecommitdiffstats
path: root/capstone/suite/fuzz
diff options
context:
space:
mode:
Diffstat (limited to 'capstone/suite/fuzz')
-rw-r--r--capstone/suite/fuzz/Makefile112
-rw-r--r--capstone/suite/fuzz/README2
-rw-r--r--capstone/suite/fuzz/README.md34
-rw-r--r--capstone/suite/fuzz/driverbin.c88
-rw-r--r--capstone/suite/fuzz/drivermc.c138
-rw-r--r--capstone/suite/fuzz/fuzz_decode_platform.c27
-rw-r--r--capstone/suite/fuzz/fuzz_diff.c237
-rw-r--r--capstone/suite/fuzz/fuzz_disasm.c99
-rw-r--r--capstone/suite/fuzz/fuzz_disasm.options2
-rw-r--r--capstone/suite/fuzz/fuzz_harness.c222
-rw-r--r--capstone/suite/fuzz/fuzz_llvm.cpp41
-rwxr-xr-xcapstone/suite/fuzz/fuzzit.sh27
-rw-r--r--capstone/suite/fuzz/fuzzitid.txt3
-rw-r--r--capstone/suite/fuzz/onefile.c51
-rw-r--r--capstone/suite/fuzz/platform.c365
-rw-r--r--capstone/suite/fuzz/platform.h24
16 files changed, 1472 insertions, 0 deletions
diff --git a/capstone/suite/fuzz/Makefile b/capstone/suite/fuzz/Makefile
new file mode 100644
index 000000000..e0c0ef2b8
--- /dev/null
+++ b/capstone/suite/fuzz/Makefile
@@ -0,0 +1,112 @@
+# 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
+
+BIN_EXT =
+AR_EXT = a
+
+
+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"
+
+$(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 $@
diff --git a/capstone/suite/fuzz/README b/capstone/suite/fuzz/README
new file mode 100644
index 000000000..0e637936d
--- /dev/null
+++ b/capstone/suite/fuzz/README
@@ -0,0 +1,2 @@
+This directory contains a fuzz testing harness for Capstone.
+Run "make" to compile this code.
diff --git a/capstone/suite/fuzz/README.md b/capstone/suite/fuzz/README.md
new file mode 100644
index 000000000..27c1c0c36
--- /dev/null
+++ b/capstone/suite/fuzz/README.md
@@ -0,0 +1,34 @@
+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
+
+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`
+
+Fuzzit integration
+------
+
+Travis will build the fuzz target with the different sanitizers.
+Then, Travis will launch sanity fuzzit jobs as part of continuous integration (for each of the sanitizers)
+The fuzzit target ids are stored in a configuration file fuzzitid.txt and used by fuzzit.sh
diff --git a/capstone/suite/fuzz/driverbin.c b/capstone/suite/fuzz/driverbin.c
new file mode 100644
index 000000000..d5e3a0fcc
--- /dev/null
+++ b/capstone/suite/fuzz/driverbin.c
@@ -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");
+
+ //lauch fuzzer
+ LLVMFuzzerTestOneInput(Data, Size);
+ fclose(fp);
+ }
+ closedir(d);
+ printf("Ok : whole directory finished\n");
+ return r;
+}
+
diff --git a/capstone/suite/fuzz/drivermc.c b/capstone/suite/fuzz/drivermc.c
new file mode 100644
index 000000000..ff31ebdee
--- /dev/null
+++ b/capstone/suite/fuzz/drivermc.c
@@ -0,0 +1,138 @@
+#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_SYSZ") == 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_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;
+ }
+ }
+ //lauch fuzzer
+ LLVMFuzzerTestOneInput(Data, Size);
+ }
+ fclose(fp);
+ }
+ return 0;
+}
+
diff --git a/capstone/suite/fuzz/fuzz_decode_platform.c b/capstone/suite/fuzz/fuzz_decode_platform.c
new file mode 100644
index 000000000..d79c4ea34
--- /dev/null
+++ b/capstone/suite/fuzz/fuzz_decode_platform.c
@@ -0,0 +1,27 @@
+// 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;
+}
+
diff --git a/capstone/suite/fuzz/fuzz_diff.c b/capstone/suite/fuzz/fuzz_diff.c
new file mode 100644
index 000000000..f0f39fdc6
--- /dev/null
+++ b/capstone/suite/fuzz/fuzz_diff.c
@@ -0,0 +1,237 @@
+
+#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_SYSZ,
+ (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"
+ },
+};
+
+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;
+}
diff --git a/capstone/suite/fuzz/fuzz_disasm.c b/capstone/suite/fuzz/fuzz_disasm.c
new file mode 100644
index 000000000..0dd7ef72d
--- /dev/null
+++ b/capstone/suite/fuzz/fuzz_disasm.c
@@ -0,0 +1,99 @@
+// 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 *i = &(all_insn[j]);
+ fprintf(outfile, "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) {
+ 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;
+}
diff --git a/capstone/suite/fuzz/fuzz_disasm.options b/capstone/suite/fuzz/fuzz_disasm.options
new file mode 100644
index 000000000..9fda93fcb
--- /dev/null
+++ b/capstone/suite/fuzz/fuzz_disasm.options
@@ -0,0 +1,2 @@
+[libfuzzer]
+max_len = 4096
diff --git a/capstone/suite/fuzz/fuzz_harness.c b/capstone/suite/fuzz/fuzz_harness.c
new file mode 100644
index 000000000..b69d3ba47
--- /dev/null
+++ b/capstone/suite/fuzz/fuzz_harness.c
@@ -0,0 +1,222 @@
+#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_SYSZ,
+ (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"
+ },
+ };
+
+ // 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;
+}
diff --git a/capstone/suite/fuzz/fuzz_llvm.cpp b/capstone/suite/fuzz/fuzz_llvm.cpp
new file mode 100644
index 000000000..7e713cb1e
--- /dev/null
+++ b/capstone/suite/fuzz/fuzz_llvm.cpp
@@ -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;
+}
diff --git a/capstone/suite/fuzz/fuzzit.sh b/capstone/suite/fuzz/fuzzit.sh
new file mode 100755
index 000000000..b962b773e
--- /dev/null
+++ b/capstone/suite/fuzz/fuzzit.sh
@@ -0,0 +1,27 @@
+FUZZIT_API_KEY=f10b19a56d96b29dfdfe459d41b3d82e475e49c737095c74c99d65a032d5c2ab84d44dad510886bc824f101a860b1754
+
+[ -s ./suite/fuzz/fuzz_bindisasm2 ] || exit 0
+
+if [ ${TRAVIS_EVENT_TYPE} -eq 'cron' ]; then
+ FUZZING_TYPE=fuzzing
+else
+ FUZZING_TYPE=sanity
+fi
+if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
+ FUZZIT_BRANCH="${TRAVIS_BRANCH}"
+else
+ FUZZIT_BRANCH="PR-${TRAVIS_PULL_REQUEST}"
+fi
+
+FUZZIT_ARGS="--type ${FUZZING_TYPE} --branch ${FUZZIT_BRANCH} --revision ${TRAVIS_COMMIT}"
+if [ -n "$UBSAN_OPTIONS" ]; then
+ FUZZIT_ARGS+=" --ubsan_options ${UBSAN_OPTIONS}"
+fi
+wget -O fuzzit https://github.com/fuzzitdev/fuzzit/releases/download/v1.2.5/fuzzit_1.2.5_Linux_x86_64
+chmod +x fuzzit
+./fuzzit auth ${FUZZIT_API_KEY}
+set -x
+grep "$QA_FUZZIT" suite/fuzz/fuzzitid.txt | cut -d" " -f2 | while read i; do
+ ./fuzzit c job ${FUZZIT_ARGS} ${i} ./suite/fuzz/fuzz_bindisasm2
+done
+set +x
diff --git a/capstone/suite/fuzz/fuzzitid.txt b/capstone/suite/fuzz/fuzzitid.txt
new file mode 100644
index 000000000..57bbe73ca
--- /dev/null
+++ b/capstone/suite/fuzz/fuzzitid.txt
@@ -0,0 +1,3 @@
+asan A1NqPndmOVrguCNj95LZ
+msan JchjH3j58fOnB8ZXGyWl
+ubsan JqHqVabfDEqitOusrPFx \ No newline at end of file
diff --git a/capstone/suite/fuzz/onefile.c b/capstone/suite/fuzz/onefile.c
new file mode 100644
index 000000000..74be3063a
--- /dev/null
+++ b/capstone/suite/fuzz/onefile.c
@@ -0,0 +1,51 @@
+#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;
+ }
+
+ //lauch fuzzer
+ LLVMFuzzerTestOneInput(Data, Size);
+ free(Data);
+ fclose(fp);
+ return 0;
+}
+
diff --git a/capstone/suite/fuzz/platform.c b/capstone/suite/fuzz/platform.c
new file mode 100644
index 000000000..d70cdfef1
--- /dev/null
+++ b/capstone/suite/fuzz/platform.c
@@ -0,0 +1,365 @@
+#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_ARM64,
+ (cs_mode)0,
+ "ARM-64",
+ "arm64"
+ },
+ {
+ // 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_SYSZ,
+ (cs_mode)0,
+ "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"
+ },
+ {
+ //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"
+ },
+
+ // 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)
+{
+ return n % platform_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;
+}
+
diff --git a/capstone/suite/fuzz/platform.h b/capstone/suite/fuzz/platform.h
new file mode 100644
index 000000000..29e03f989
--- /dev/null
+++ b/capstone/suite/fuzz/platform.h
@@ -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