From 6c921793af1a39d2edcc4a8f5789f6c0f3f0f1ca Mon Sep 17 00:00:00 2001 From: xjd Date: Wed, 8 May 2024 15:14:15 +0800 Subject: [PATCH] Add fuzzing tests to C code --- bindings/c/include/molecule_reader.h | 11 + fuzzing/.gitignore | 7 + fuzzing/Makefile | 53 +++ fuzzing/README.md | 19 + fuzzing/corpus/.gitignore | 1 + fuzzing/coverage.c | 35 ++ fuzzing/definitions.h | 424 ++++++++++++++++++ fuzzing/definitions.mol | 26 ++ fuzzing/fuzzer.c | 6 + fuzzing/fuzzer_func.h | 100 +++++ fuzzing/manually-gen.c | 61 +++ .../src/generator/languages/c/reader.rs | 9 + 12 files changed, 752 insertions(+) create mode 100644 fuzzing/.gitignore create mode 100644 fuzzing/Makefile create mode 100644 fuzzing/README.md create mode 100644 fuzzing/corpus/.gitignore create mode 100644 fuzzing/coverage.c create mode 100644 fuzzing/definitions.h create mode 100644 fuzzing/definitions.mol create mode 100644 fuzzing/fuzzer.c create mode 100644 fuzzing/fuzzer_func.h create mode 100644 fuzzing/manually-gen.c diff --git a/bindings/c/include/molecule_reader.h b/bindings/c/include/molecule_reader.h index c647f0b..f9d8fba 100644 --- a/bindings/c/include/molecule_reader.h +++ b/bindings/c/include/molecule_reader.h @@ -235,6 +235,17 @@ MOLECULE_API_DECORATOR mol_seg_t mol_fixvec_slice_raw_bytes(const mol_seg_t *inp return seg; } +// Check if a segment(`part`) is contained by `total` +MOLECULE_API_DECORATOR bool mol_contained_by(const mol_seg_t *part, const mol_seg_t* total) { + if (part->ptr < total->ptr) { + return MOL_ERR_OFFSET; + } + if ((part->ptr + part->size) > (total->ptr + total->size)) { + return MOL_ERR_OFFSET; + } + return MOL_OK; +} + /* * Undef macros which are internal use only. */ diff --git a/fuzzing/.gitignore b/fuzzing/.gitignore new file mode 100644 index 0000000..7fb028d --- /dev/null +++ b/fuzzing/.gitignore @@ -0,0 +1,7 @@ +fuzzer +coverage +fuzz-*.log +crash-* +*.profraw +coverage_dir +manually-gen \ No newline at end of file diff --git a/fuzzing/Makefile b/fuzzing/Makefile new file mode 100644 index 0000000..c7db0bf --- /dev/null +++ b/fuzzing/Makefile @@ -0,0 +1,53 @@ + +NPROC?=$(shell nproc) +CC=clang-16 +LLVM_PROFDATA=llvm-profdata-16 +LLVM_COV=llvm-cov-16 +CORPUS_DIR=corpus + +FUZZER_FLAGS=-g -O1 -fsanitize=fuzzer,address,undefined -I ../bindings/c/include -I . + +COVERAGE_DIR=coverage_dir +COVERAGE_FLAGS=-g -fprofile-instr-generate -fcoverage-mapping -I ../bindings/c/include -I . + +EXTERNAL_HEADERS=./fuzzer_func.h ../bindings/c/include/molecule_reader.h + +all: fuzzer coverage + +show: $(COVERAGE_DIR)/fuzzer.profdata + $(LLVM_COV) show --instr-profile=$(COVERAGE_DIR)/fuzzer.profdata coverage + +report: $(COVERAGE_DIR)/fuzzer.profdata coverage $(EXTERNAL_HEADERS) + $(LLVM_COV) report --show-functions --instr-profile=$(COVERAGE_DIR)/fuzzer.profdata coverage $(EXTERNAL_HEADERS) + +fuzzer: $(EXTERNAL_HEADERS) + $(CC) $(FUZZER_FLAGS) fuzzer.c -o fuzzer + +coverage: $(EXTERNAL_HEADERS) + $(CC) $(COVERAGE_FLAGS) coverage.c fuzzer.c -o coverage + +start-fuzzer: fuzzer + ./fuzzer -max_len=255 -workers=$(NPROC) -jobs=$(NPROC) corpus + +clean: + rm -rf fuzzer coverage + +gen: + moleculec --language c --schema-file definitions.mol | clang-format > definitions.h + +manually-gen: + $(CC) -I ../bindings/c/include -I . manually-gen.c -o manually-gen + ./manually-gen + +fmt: + clang-format -style="{BasedOnStyle: google, IndentWidth: 4, SortIncludes: false}" -i *.c *.h + +%.profraw: coverage + LLVM_PROFILE_FILE=$@ ./coverage $(CORPUS_DIR)/* + +%.profdata: %.profraw + $(LLVM_PROFDATA) merge --sparse $< -o $@ + +.PHONY: all fuzzer coverage report + +.PRECIOUS: $(COVERAGE_DIR)/fuzzer.profraw $(COVERAGE_DIR)/fuzzer.profdata diff --git a/fuzzing/README.md b/fuzzing/README.md new file mode 100644 index 0000000..6344541 --- /dev/null +++ b/fuzzing/README.md @@ -0,0 +1,19 @@ + + +### Requirement + +* Linux +* LLVM version 16 + + +### Build + +``` +make all +``` + +### Run + +``` +make start-fuzzer +``` diff --git a/fuzzing/corpus/.gitignore b/fuzzing/corpus/.gitignore new file mode 100644 index 0000000..72e8ffc --- /dev/null +++ b/fuzzing/corpus/.gitignore @@ -0,0 +1 @@ +* diff --git a/fuzzing/coverage.c b/fuzzing/coverage.c new file mode 100644 index 0000000..02e7ca3 --- /dev/null +++ b/fuzzing/coverage.c @@ -0,0 +1,35 @@ +//===----------------------------------------------------------------------===// +// This main() function can be linked to a fuzz target (i.e. a library +// that exports LLVMFuzzerTestOneInput() and possibly LLVMFuzzerInitialize()) +// instead of libFuzzer. This main() function will not perform any fuzzing +// but will simply feed all input files one by one to the fuzz target. +// +// Use this file to provide reproducers for bugs when linking against libFuzzer +// or other fuzzing engine is undesirable. +//===----------------------------------------------------------------------===*/ +#include +#include +#include + +extern int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size); +__attribute__((weak)) extern int LLVMFuzzerInitialize(int *argc, char ***argv); + +int main(int argc, char **argv) { + fprintf(stderr, "StandaloneFuzzTargetMain: running %d inputs\n", argc - 1); + if (LLVMFuzzerInitialize) LLVMFuzzerInitialize(&argc, &argv); + for (int i = 1; i < argc; i++) { + fprintf(stderr, "Running: %s\n", argv[i]); + FILE *f = fopen(argv[i], "r"); + assert(f); + fseek(f, 0, SEEK_END); + size_t len = ftell(f); + fseek(f, 0, SEEK_SET); + unsigned char *buf = (unsigned char *)malloc(len); + size_t n_read = fread(buf, 1, len, f); + fclose(f); + assert(n_read == len); + LLVMFuzzerTestOneInput(buf, len); + free(buf); + fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read); + } +} diff --git a/fuzzing/definitions.h b/fuzzing/definitions.h new file mode 100644 index 0000000..889c6ef --- /dev/null +++ b/fuzzing/definitions.h @@ -0,0 +1,424 @@ +// Generated by Molecule 0.7.5 + +#define MOLECULEC_VERSION 7005 +#define MOLECULE_API_VERSION_MIN 7000 + +#include "molecule_reader.h" +#include "molecule_builder.h" + +#ifndef DEFINITIONS_H +#define DEFINITIONS_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#ifndef MOLECULE_API_DECORATOR +#define __DEFINE_MOLECULE_API_DECORATOR_DEFINITIONS +#define MOLECULE_API_DECORATOR +#endif /* MOLECULE_API_DECORATOR */ + +/* + * Reader APIs + */ + +#define MolReader_ArrayType_verify(s, c) mol_verify_fixed_size(s, 3) +#define MolReader_ArrayType_get_nth0(s) mol_slice_by_offset(s, 0, 1) +#define MolReader_ArrayType_get_nth1(s) mol_slice_by_offset(s, 1, 1) +#define MolReader_ArrayType_get_nth2(s) mol_slice_by_offset(s, 2, 1) +#define MolReader_StructType_verify(s, c) mol_verify_fixed_size(s, 4) +#define MolReader_StructType_get_f1(s) mol_slice_by_offset(s, 0, 3) +#define MolReader_StructType_get_f2(s) mol_slice_by_offset(s, 3, 1) +#define MolReader_FixVecType_verify(s, c) mol_fixvec_verify(s, 1) +#define MolReader_FixVecType_length(s) mol_fixvec_length(s) +#define MolReader_FixVecType_get(s, i) mol_fixvec_slice_by_index(s, 1, i) +#define MolReader_FixVecType_raw_bytes(s) mol_fixvec_slice_raw_bytes(s) +MOLECULE_API_DECORATOR mol_errno MolReader_DynVecType_verify(const mol_seg_t *, + bool); +#define MolReader_DynVecType_length(s) mol_dynvec_length(s) +#define MolReader_DynVecType_get(s, i) mol_dynvec_slice_by_index(s, i) +MOLECULE_API_DECORATOR mol_errno MolReader_OptType_verify(const mol_seg_t *, + bool); +#define MolReader_OptType_is_none(s) mol_option_is_none(s) +MOLECULE_API_DECORATOR mol_errno MolReader_TableType_verify(const mol_seg_t *, + bool); +#define MolReader_TableType_actual_field_count(s) \ + mol_table_actual_field_count(s) +#define MolReader_TableType_has_extra_fields(s) mol_table_has_extra_fields(s, 5) +#define MolReader_TableType_get_f1(s) mol_table_slice_by_index(s, 0) +#define MolReader_TableType_get_f2(s) mol_table_slice_by_index(s, 1) +#define MolReader_TableType_get_f3(s) mol_table_slice_by_index(s, 2) +#define MolReader_TableType_get_f4(s) mol_table_slice_by_index(s, 3) +#define MolReader_TableType_get_f5(s) mol_table_slice_by_index(s, 4) +MOLECULE_API_DECORATOR mol_errno MolReader_UnionType_verify(const mol_seg_t *, + bool); +#define MolReader_UnionType_unpack(s) mol_union_unpack(s) + +/* + * Builder APIs + */ + +#define MolBuilder_ArrayType_init(b) mol_builder_initialize_fixed_size(b, 3) +#define MolBuilder_ArrayType_set_nth0(b, p) \ + mol_builder_set_byte_by_offset(b, 0, p) +#define MolBuilder_ArrayType_set_nth1(b, p) \ + mol_builder_set_byte_by_offset(b, 1, p) +#define MolBuilder_ArrayType_set_nth2(b, p) \ + mol_builder_set_byte_by_offset(b, 2, p) +#define MolBuilder_ArrayType_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_ArrayType_clear(b) mol_builder_discard(b) +#define MolBuilder_StructType_init(b) mol_builder_initialize_fixed_size(b, 4) +#define MolBuilder_StructType_set_f1(b, p) mol_builder_set_by_offset(b, 0, p, 3) +#define MolBuilder_StructType_set_f2(b, p) \ + mol_builder_set_byte_by_offset(b, 3, p) +#define MolBuilder_StructType_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_StructType_clear(b) mol_builder_discard(b) +#define MolBuilder_FixVecType_init(b) mol_fixvec_builder_initialize(b, 16) +#define MolBuilder_FixVecType_push(b, p) mol_fixvec_builder_push_byte(b, p) +#define MolBuilder_FixVecType_build(b) mol_fixvec_builder_finalize(b) +#define MolBuilder_FixVecType_clear(b) mol_builder_discard(b) +#define MolBuilder_DynVecType_init(b) \ + mol_builder_initialize_with_capacity(b, 64, 64) +#define MolBuilder_DynVecType_push(b, p, l) mol_dynvec_builder_push(b, p, l) +#define MolBuilder_DynVecType_build(b) mol_dynvec_builder_finalize(b) +#define MolBuilder_DynVecType_clear(b) mol_builder_discard(b) +#define MolBuilder_OptType_init(b) mol_builder_initialize_fixed_size(b, 0) +#define MolBuilder_OptType_set(b, p, l) mol_option_builder_set(b, p, l) +#define MolBuilder_OptType_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_OptType_clear(b) mol_builder_discard(b) +#define MolBuilder_TableType_init(b) mol_table_builder_initialize(b, 256, 5) +#define MolBuilder_TableType_set_f1(b, p, l) mol_table_builder_add(b, 0, p, l) +#define MolBuilder_TableType_set_f2(b, p, l) mol_table_builder_add(b, 1, p, l) +#define MolBuilder_TableType_set_f3(b, p, l) mol_table_builder_add(b, 2, p, l) +#define MolBuilder_TableType_set_f4(b, p, l) mol_table_builder_add(b, 3, p, l) +#define MolBuilder_TableType_set_f5(b, p, l) mol_table_builder_add(b, 4, p, l) +MOLECULE_API_DECORATOR mol_seg_res_t MolBuilder_TableType_build(mol_builder_t); +#define MolBuilder_TableType_clear(b) mol_builder_discard(b) +#define MolBuilder_UnionType_init(b) \ + mol_union_builder_initialize(b, 8, 0, MolDefault_ArrayType, 3) +#define MolBuilder_UnionType_set_ArrayType(b, p, l) \ + mol_union_builder_set(b, 0, p, l) +#define MolBuilder_UnionType_set_StructType(b, p, l) \ + mol_union_builder_set(b, 1, p, l) +#define MolBuilder_UnionType_set_FixVecType(b, p, l) \ + mol_union_builder_set(b, 2, p, l) +#define MolBuilder_UnionType_set_DynVecType(b, p, l) \ + mol_union_builder_set(b, 3, p, l) +#define MolBuilder_UnionType_set_TableType(b, p, l) \ + mol_union_builder_set(b, 4, p, l) +#define MolBuilder_UnionType_build(b) mol_builder_finalize_simple(b) +#define MolBuilder_UnionType_clear(b) mol_builder_discard(b) + +/* + * Default Value + */ + +#define ____ 0x00 + +MOLECULE_API_DECORATOR const uint8_t MolDefault_ArrayType[3] = {____, ____, + ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_StructType[4] = {____, ____, + ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_FixVecType[4] = {____, ____, + ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_DynVecType[4] = {0x04, ____, + ____, ____}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_OptType[0] = {}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_TableType[39] = { + 0x27, ____, ____, ____, 0x18, ____, ____, ____, 0x1c, ____, + ____, ____, 0x20, ____, ____, ____, 0x24, ____, ____, ____, + 0x27, ____, ____, ____, ____, ____, ____, ____, 0x04, ____, + ____, ____, ____, ____, ____, ____, ____, ____, ____, +}; +MOLECULE_API_DECORATOR const uint8_t MolDefault_UnionType[7] = { + ____, ____, ____, ____, ____, ____, ____, +}; + +#undef ____ + +/* + * Reader Functions + */ + +MOLECULE_API_DECORATOR mol_errno +MolReader_DynVecType_verify(const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + uint8_t *ptr = input->ptr; + mol_num_t total_size = mol_unpack_number(ptr); + if (input->size != total_size) { + return MOL_ERR_TOTAL_SIZE; + } + if (input->size == MOL_NUM_T_SIZE) { + return MOL_OK; + } + if (input->size < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_HEADER; + } + ptr += MOL_NUM_T_SIZE; + mol_num_t offset = mol_unpack_number(ptr); + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_OFFSET; + } + mol_num_t item_count = offset / 4 - 1; + if (input->size < MOL_NUM_T_SIZE * (item_count + 1)) { + return MOL_ERR_HEADER; + } + mol_num_t end; + for (mol_num_t i = 1; i < item_count; i++) { + ptr += MOL_NUM_T_SIZE; + end = mol_unpack_number(ptr); + if (offset > end) { + return MOL_ERR_OFFSET; + } + mol_seg_t inner; + inner.ptr = input->ptr + offset; + inner.size = end - offset; + if (mol_contained_by(&inner, input) != MOL_OK) { + return MOL_ERR_OFFSET; + } + mol_errno errno = MolReader_FixVecType_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + offset = end; + } + if (offset > total_size) { + return MOL_ERR_OFFSET; + } + mol_seg_t inner; + inner.ptr = input->ptr + offset; + inner.size = total_size - offset; + if (mol_contained_by(&inner, input) != MOL_OK) { + return MOL_ERR_OFFSET; + } + return MolReader_FixVecType_verify(&inner, compatible); +} +MOLECULE_API_DECORATOR mol_errno +MolReader_OptType_verify(const mol_seg_t *input, bool compatible) { + if (input->size != 0) { + return MolReader_DynVecType_verify(input, compatible); + } else { + return MOL_OK; + } +} +MOLECULE_API_DECORATOR mol_errno +MolReader_TableType_verify(const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + uint8_t *ptr = input->ptr; + mol_num_t total_size = mol_unpack_number(ptr); + if (input->size != total_size) { + return MOL_ERR_TOTAL_SIZE; + } + if (input->size < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_HEADER; + } + ptr += MOL_NUM_T_SIZE; + mol_num_t offset = mol_unpack_number(ptr); + if (offset % 4 > 0 || offset < MOL_NUM_T_SIZE * 2) { + return MOL_ERR_OFFSET; + } + mol_num_t field_count = offset / 4 - 1; + if (field_count < 5) { + return MOL_ERR_FIELD_COUNT; + } else if (!compatible && field_count > 5) { + return MOL_ERR_FIELD_COUNT; + } + if (input->size < MOL_NUM_T_SIZE * (field_count + 1)) { + return MOL_ERR_HEADER; + } + mol_num_t offsets[field_count + 1]; + offsets[0] = offset; + for (mol_num_t i = 1; i < field_count; i++) { + ptr += MOL_NUM_T_SIZE; + offsets[i] = mol_unpack_number(ptr); + if (offsets[i - 1] > offsets[i]) { + return MOL_ERR_OFFSET; + } + } + if (offsets[field_count - 1] > total_size) { + return MOL_ERR_OFFSET; + } + offsets[field_count] = total_size; + mol_seg_t inner; + mol_errno errno; + inner.ptr = input->ptr + offsets[0]; + inner.size = offsets[1] - offsets[0]; + if (mol_contained_by(&inner, input) != MOL_OK) { + return MOL_ERR_OFFSET; + } + errno = MolReader_FixVecType_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[1]; + inner.size = offsets[2] - offsets[1]; + if (mol_contained_by(&inner, input) != MOL_OK) { + return MOL_ERR_OFFSET; + } + errno = MolReader_DynVecType_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[2]; + inner.size = offsets[3] - offsets[2]; + if (mol_contained_by(&inner, input) != MOL_OK) { + return MOL_ERR_OFFSET; + } + errno = MolReader_StructType_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[3]; + inner.size = offsets[4] - offsets[3]; + if (mol_contained_by(&inner, input) != MOL_OK) { + return MOL_ERR_OFFSET; + } + errno = MolReader_ArrayType_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + inner.ptr = input->ptr + offsets[4]; + inner.size = offsets[5] - offsets[4]; + if (mol_contained_by(&inner, input) != MOL_OK) { + return MOL_ERR_OFFSET; + } + errno = MolReader_OptType_verify(&inner, compatible); + if (errno != MOL_OK) { + return MOL_ERR_DATA; + } + return MOL_OK; +} +MOLECULE_API_DECORATOR mol_errno +MolReader_UnionType_verify(const mol_seg_t *input, bool compatible) { + if (input->size < MOL_NUM_T_SIZE) { + return MOL_ERR_HEADER; + } + mol_num_t item_id = mol_unpack_number(input->ptr); + mol_seg_t inner; + inner.ptr = input->ptr + MOL_NUM_T_SIZE; + inner.size = input->size - MOL_NUM_T_SIZE; + switch (item_id) { + case 0: + return MolReader_ArrayType_verify(&inner, compatible); + case 1: + return MolReader_StructType_verify(&inner, compatible); + case 2: + return MolReader_FixVecType_verify(&inner, compatible); + case 3: + return MolReader_DynVecType_verify(&inner, compatible); + case 4: + return MolReader_TableType_verify(&inner, compatible); + default: + return MOL_ERR_UNKNOWN_ITEM; + } +} + +/* + * Builder Functions + */ + +MOLECULE_API_DECORATOR mol_seg_res_t +MolBuilder_TableType_build(mol_builder_t builder) { + mol_seg_res_t res; + res.errno = MOL_OK; + mol_num_t offset = 24; + mol_num_t len; + res.seg.size = offset; + len = builder.number_ptr[1]; + res.seg.size += len == 0 ? 4 : len; + len = builder.number_ptr[3]; + res.seg.size += len == 0 ? 4 : len; + len = builder.number_ptr[5]; + res.seg.size += len == 0 ? 4 : len; + len = builder.number_ptr[7]; + res.seg.size += len == 0 ? 3 : len; + len = builder.number_ptr[9]; + res.seg.size += len == 0 ? 0 : len; + res.seg.ptr = (uint8_t *)malloc(res.seg.size); + uint8_t *dst = res.seg.ptr; + mol_pack_number(dst, &res.seg.size); + dst += MOL_NUM_T_SIZE; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[1]; + offset += len == 0 ? 4 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[3]; + offset += len == 0 ? 4 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[5]; + offset += len == 0 ? 4 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[7]; + offset += len == 0 ? 3 : len; + mol_pack_number(dst, &offset); + dst += MOL_NUM_T_SIZE; + len = builder.number_ptr[9]; + offset += len == 0 ? 0 : len; + uint8_t *src = builder.data_ptr; + len = builder.number_ptr[1]; + if (len == 0) { + len = 4; + memcpy(dst, &MolDefault_FixVecType, len); + } else { + mol_num_t of = builder.number_ptr[0]; + memcpy(dst, src + of, len); + } + dst += len; + len = builder.number_ptr[3]; + if (len == 0) { + len = 4; + memcpy(dst, &MolDefault_DynVecType, len); + } else { + mol_num_t of = builder.number_ptr[2]; + memcpy(dst, src + of, len); + } + dst += len; + len = builder.number_ptr[5]; + if (len == 0) { + len = 4; + memcpy(dst, &MolDefault_StructType, len); + } else { + mol_num_t of = builder.number_ptr[4]; + memcpy(dst, src + of, len); + } + dst += len; + len = builder.number_ptr[7]; + if (len == 0) { + len = 3; + memcpy(dst, &MolDefault_ArrayType, len); + } else { + mol_num_t of = builder.number_ptr[6]; + memcpy(dst, src + of, len); + } + dst += len; + len = builder.number_ptr[9]; + if (len == 0) { + len = 0; + memcpy(dst, &MolDefault_OptType, len); + } else { + mol_num_t of = builder.number_ptr[8]; + memcpy(dst, src + of, len); + } + dst += len; + mol_builder_discard(builder); + return res; +} + +#ifdef __DEFINE_MOLECULE_API_DECORATOR_DEFINITIONS +#undef MOLECULE_API_DECORATOR +#undef __DEFINE_MOLECULE_API_DECORATOR_DEFINITIONS +#endif /* __DEFINE_MOLECULE_API_DECORATOR_DEFINITIONS */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* DEFINITIONS_H */ diff --git a/fuzzing/definitions.mol b/fuzzing/definitions.mol new file mode 100644 index 0000000..77c2493 --- /dev/null +++ b/fuzzing/definitions.mol @@ -0,0 +1,26 @@ +array ArrayType [byte; 3]; + +struct StructType { + f1: ArrayType, + f2: byte, +} + +vector FixVecType ; +vector DynVecType ; +option OptType (DynVecType); + +table TableType { + f1: FixVecType, + f2: DynVecType, + f3: StructType, + f4: ArrayType, + f5: OptType, +} + +union UnionType { + ArrayType, + StructType, + FixVecType, + DynVecType, + TableType, +} diff --git a/fuzzing/fuzzer.c b/fuzzing/fuzzer.c new file mode 100644 index 0000000..f41caf9 --- /dev/null +++ b/fuzzing/fuzzer.c @@ -0,0 +1,6 @@ + +#include "fuzzer_func.h" + +int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) { + return start_fuzzing(data, size); +} diff --git a/fuzzing/fuzzer_func.h b/fuzzing/fuzzer_func.h new file mode 100644 index 0000000..fbbe9eb --- /dev/null +++ b/fuzzing/fuzzer_func.h @@ -0,0 +1,100 @@ + +#ifndef _FUZZER_FUZZER_FUNC_H_ +#define _FUZZER_FUZZER_FUNC_H_ +#include +#include +#include + +#include "definitions.h" + +void access_seg(mol_seg_t seg, int* result) { + if (seg.size > 0) { + *result += (int)seg.ptr[0]; + *result += (int)seg.ptr[seg.size - 1]; + } +} + +void access_array(mol_seg_t seg, int* result) { + if (MolReader_ArrayType_verify(&seg, false) == 0) { + mol_seg_t first = MolReader_ArrayType_get_nth0(&seg); + mol_seg_t last = MolReader_ArrayType_get_nth2(&seg); + access_seg(first, result); + access_seg(last, result); + } +} + +void access_struct(mol_seg_t seg, int* result) { + if (MolReader_StructType_verify(&seg, false) == 0) { + mol_seg_t f1 = MolReader_StructType_get_f1(&seg); + mol_seg_t f2 = MolReader_StructType_get_f2(&seg); + access_seg(f1, result); + access_seg(f2, result); + } +} + +void access_fixvec(mol_seg_t seg, int* result) { + if (MolReader_FixVecType_verify(&seg, false) == 0) { + mol_seg_t data = MolReader_FixVecType_raw_bytes(&seg); + access_seg(data, result); + } +} + +void access_dynvec(mol_seg_t seg, int* result) { + if (MolReader_DynVecType_verify(&seg, false) == 0) { + uint32_t length = MolReader_DynVecType_length(&seg); + for (uint32_t i = 0; i < length; i++) { + mol_seg_res_t element = MolReader_DynVecType_get(&seg, i); + access_seg(element.seg, result); + } + mol_seg_res_t out_of_bound = MolReader_DynVecType_get(&seg, length); + assert(out_of_bound.errno != 0); + } +} + +void access_opt(mol_seg_t seg, int* result) { + if (MolReader_OptType_verify(&seg, false) == 0) { + if (MolReader_OptType_is_none(&seg)) { + return; + } else { + access_dynvec(seg, result); + } + } +} + +void access_table(mol_seg_t seg, int* result) { + if (MolReader_TableType_verify(&seg, false) == 0) { + mol_seg_t fixvec = MolReader_TableType_get_f1(&seg); + access_fixvec(fixvec, result); + mol_seg_t dynvec = MolReader_TableType_get_f2(&seg); + access_dynvec(dynvec, result); + mol_seg_t struct_ = MolReader_TableType_get_f3(&seg); + access_struct(struct_, result); + mol_seg_t array = MolReader_TableType_get_f4(&seg); + access_array(array, result); + mol_seg_t opt = MolReader_TableType_get_f5(&seg); + access_opt(opt, result); + } +} + +void access_union(mol_seg_t seg, int* result) { + if (MolReader_UnionType_verify(&seg, false) == 0) { + mol_union_t data = MolReader_UnionType_unpack(&seg); + access_seg(data.seg, result); + } +} + +int start_fuzzing(uint8_t* data, size_t size) { + int result = 0; + mol_seg_t seg = {.ptr = data, .size = size}; + + access_array(seg, &result); + access_struct(seg, &result); + access_fixvec(seg, &result); + access_dynvec(seg, &result); + access_table(seg, &result); + access_union(seg, &result); + + return result; +} + +#endif diff --git a/fuzzing/manually-gen.c b/fuzzing/manually-gen.c new file mode 100644 index 0000000..de4bf1f --- /dev/null +++ b/fuzzing/manually-gen.c @@ -0,0 +1,61 @@ +#include +#include +#include +#include "definitions.h" + +int write(uint8_t* data, size_t length, const char* file_name) { + FILE* file = fopen(file_name, "wb"); + if (file == NULL) { + fprintf(stderr, "Error: Unable to open file %s\n", file_name); + return -1; + } + + size_t bytes_written = + fwrite(data, sizeof(uint8_t), length, file); // Write data to file + if (bytes_written != length) { + fprintf(stderr, "Error: Unable to write all data to file\n"); + fclose(file); + return -1; + } + printf("%s is generated", file_name); + fclose(file); + return 0; +} + +int main() { + mol_builder_t fixvec_builder = {0}; + MolBuilder_FixVecType_init(&fixvec_builder); + MolBuilder_FixVecType_push(&fixvec_builder, 1); + mol_seg_res_t res = MolBuilder_FixVecType_build(fixvec_builder); + assert(res.errno == 0); + mol_seg_t fix_vec = res.seg; + + mol_builder_t dynvec_builder = {0}; + MolBuilder_DynVecType_init(&dynvec_builder); + MolBuilder_DynVecType_push(&dynvec_builder, fix_vec.ptr, fix_vec.size); + res = MolBuilder_DynVecType_build(dynvec_builder); + assert(res.errno == 0); + mol_seg_t dyn_vec = res.seg; + + uint8_t array[3] = {0}; + uint8_t byte = 0; + mol_builder_t struct_builder = {0}; + MolBuilder_StructType_init(&struct_builder); + MolBuilder_StructType_set_f1(&struct_builder, array); + MolBuilder_StructType_set_f2(&struct_builder, byte); + res = MolBuilder_StructType_build(struct_builder); + assert(res.errno == 0); + mol_seg_t struct_ = res.seg; + + mol_builder_t table_builder = {0}; + MolBuilder_TableType_init(&table_builder); + MolBuilder_TableType_set_f1(&table_builder, fix_vec.ptr, fix_vec.size); + MolBuilder_TableType_set_f2(&table_builder, dyn_vec.ptr, dyn_vec.size); + MolBuilder_TableType_set_f3(&table_builder, struct_.ptr, struct_.size); + MolBuilder_TableType_set_f4(&table_builder, array, 3); + res = MolBuilder_TableType_build(table_builder); + assert(res.errno == 0); + mol_seg_t table = res.seg; + + return write(table.ptr, table.size, "corpus/sample_table"); +} diff --git a/tools/codegen/src/generator/languages/c/reader.rs b/tools/codegen/src/generator/languages/c/reader.rs index 26ec6ff..59b24b4 100644 --- a/tools/codegen/src/generator/languages/c/reader.rs +++ b/tools/codegen/src/generator/languages/c/reader.rs @@ -235,6 +235,9 @@ impl GenReader for ast::DynVec { w!(o, " mol_seg_t inner; "); w!(o, " inner.ptr = input->ptr + offset; "); w!(o, " inner.size = end - offset; "); + w!(o, " if (mol_contained_by(&inner, input)!=MOL_OK) {{"); + w!(o, " return MOL_ERR_OFFSET; "); + w!(o, " }} "); w!(o, " mol_errno errno = {}(&inner, compatible); ", f); w!(o, " if (errno != MOL_OK) {{ "); w!(o, " return MOL_ERR_DATA; "); @@ -247,6 +250,9 @@ impl GenReader for ast::DynVec { w!(o, " mol_seg_t inner; "); w!(o, " inner.ptr = input->ptr + offset; "); w!(o, " inner.size = total_size - offset; "); + w!(o, " if (mol_contained_by(&inner, input) != MOL_OK) {{ "); + w!(o, " return MOL_ERR_OFFSET; "); + w!(o, " }} "); w!(o, " return {}(&inner, compatible); ", f); w!(o, "}} "); Ok(()) @@ -350,6 +356,9 @@ impl GenReader for ast::Table { let f = format!("{}_verify", field.typ().reader_prefix()); w!(o, " inner.ptr = input->ptr + offsets[{}]; ", i); w!(o, " inner.size = offsets[{}] - offsets[{}]; ", j, i); + w!(o, " if (mol_contained_by(&inner, input)!=MOL_OK) {{"); + w!(o, " return MOL_ERR_OFFSET; "); + w!(o, " }} "); w!(o, " errno = {}(&inner, compatible); ", f); w!(o, " if (errno != MOL_OK) {{ "); w!(o, " return MOL_ERR_DATA; ");