Format C/Cpp code in ./scripts/fmt_all.sh (#653)
* format all (clang format 13) * added clang-format check * re-add missing newline * cargo doc was missing * more brackets * fixed fmt workflow * clang format * shellcheck * install clang-format-13 * update ubuntu for maximum clang-formattability * yml whitespaces * fmt * shellcheck only for .sh * oops path * ignored shellcheck warning
This commit is contained in:
parent
e4447364c2
commit
bfe69aea09
17
.github/workflows/build_and_test.yml
vendored
17
.github/workflows/build_and_test.yml
vendored
@ -41,11 +41,8 @@ jobs:
|
||||
- name: Test libafl_targets no_std
|
||||
run: cd libafl_targets && cargo test --no-default-features
|
||||
|
||||
|
||||
|
||||
|
||||
ubuntu:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
@ -55,7 +52,7 @@ jobs:
|
||||
- name: set mold linker as default linker
|
||||
uses: rui314/setup-mold@v1
|
||||
- name: Install deps
|
||||
run: sudo apt-get install -y llvm llvm-dev clang ninja-build
|
||||
run: sudo apt-get install -y llvm llvm-dev clang ninja-build clang-format-13 shellcheck
|
||||
- name: get clang version
|
||||
run: command -v llvm-config && clang -v
|
||||
- name: Install cargo-hack
|
||||
@ -80,6 +77,10 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Format
|
||||
run: cargo fmt -- --check
|
||||
- name: Run clang-format style check for C/C++ programs.
|
||||
run: clang-format-13 -n -Werror --style=file $(find . -type f \( -name '*.cpp' -o -iname '*.hpp' -o -name '*.cc' -o -name '*.cxx' -o -name '*.cc' -o -name '*.h' \) | grep -v '/target/' | grep -v 'libpng-1\.6\.37' | grep -v 'stb_image\.h' | grep -v 'dlmalloc\.c')
|
||||
- name: run shellcheck
|
||||
run: shellcheck ./scripts/*.sh
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build Docs
|
||||
run: cargo doc
|
||||
@ -87,6 +88,7 @@ jobs:
|
||||
run: cargo +nightly test --doc --all-features
|
||||
- name: Run clippy
|
||||
run: ./scripts/clippy.sh
|
||||
|
||||
ubuntu-concolic:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@ -100,6 +102,7 @@ jobs:
|
||||
run: sudo ./libafl_concolic/test/smoke_test_ubuntu_deps.sh
|
||||
- name: Run smoke test
|
||||
run: ./libafl_concolic/test/smoke_test.sh
|
||||
|
||||
bindings:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@ -117,6 +120,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Run a maturin build
|
||||
run: cd ./bindings/pylibafl && maturin build
|
||||
|
||||
fuzzers:
|
||||
env:
|
||||
CC: ccache clang # use ccache in default
|
||||
@ -158,6 +162,7 @@ jobs:
|
||||
if: runner.os == 'macOS' # use bash v4
|
||||
run: /usr/local/bin/bash ./scripts/test_all_fuzzers.sh
|
||||
- run: ccache --show-stats
|
||||
|
||||
nostd-build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@ -177,12 +182,14 @@ jobs:
|
||||
run: cd ./libafl && cargo test --no-default-features
|
||||
- name: libafl armv6m-none-eabi (32 bit no_std) clippy
|
||||
run: cd ./libafl && cargo clippy --target thumbv6m-none-eabi --no-default-features
|
||||
|
||||
build-docker:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build docker
|
||||
run: docker build -t libafl .
|
||||
|
||||
windows:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
|
@ -6,13 +6,13 @@
|
||||
|
||||
#define MAX_INPUT_SIZE 3
|
||||
#define SHMEM_COUNT 100
|
||||
int shmid;
|
||||
int shmid;
|
||||
key_t key = 58974;
|
||||
|
||||
int create_shmem_array() {
|
||||
shmid = shmget(key, SHMEM_COUNT * sizeof(uint8_t), IPC_CREAT | 0666);
|
||||
printf("created a shared memory segment with shmid=%d\n", shmid);
|
||||
void *res = shmat(shmid, NULL, 0);
|
||||
void *res = shmat(shmid, NULL, 0);
|
||||
uint8_t *array_ptr = (uint8_t *)res;
|
||||
for (int i = 0; i < SHMEM_COUNT; i++) {
|
||||
array_ptr[i] = 0;
|
||||
@ -21,22 +21,20 @@ int create_shmem_array() {
|
||||
}
|
||||
|
||||
int set_value(int i) {
|
||||
void *res = shmat(shmid, NULL, 0);
|
||||
void *res = shmat(shmid, NULL, 0);
|
||||
uint8_t *array_ptr = (uint8_t *)res;
|
||||
array_ptr[i] = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t get_value(int i) {
|
||||
void *res = shmat(shmid, NULL, 0);
|
||||
void *res = shmat(shmid, NULL, 0);
|
||||
uint8_t *array_ptr = (uint8_t *)res;
|
||||
return array_ptr[i];
|
||||
}
|
||||
|
||||
int destroy_shmem(int id) {
|
||||
if (-1 == shmctl(id, IPC_RMID, NULL)) {
|
||||
return -1;
|
||||
}
|
||||
if (-1 == shmctl(id, IPC_RMID, NULL)) { return -1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
#define MAP_SIZE 100
|
||||
|
||||
// uint8_t *array;
|
||||
uint8_t array[MAP_SIZE];
|
||||
uint8_t array[MAP_SIZE];
|
||||
uint8_t *array_ptr = &array;
|
||||
|
||||
int init() {
|
||||
|
@ -35,9 +35,7 @@ uint8_t get_value(int i) {
|
||||
}
|
||||
|
||||
int destroy_shmem() {
|
||||
if (-1 == shmctl(shmid, IPC_RMID, NULL)) {
|
||||
return -1;
|
||||
}
|
||||
if (-1 == shmctl(shmid, IPC_RMID, NULL)) { return -1; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -5,11 +5,8 @@
|
||||
__AFL_FUZZ_INIT();
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
FILE *file = stdin;
|
||||
if (argc > 1) {
|
||||
file = fopen(argv[1], "rb");
|
||||
}
|
||||
if (argc > 1) { file = fopen(argv[1], "rb"); }
|
||||
|
||||
// The following three lines are for normal fuzzing.
|
||||
/*
|
||||
|
@ -6,39 +6,30 @@
|
||||
__AFL_FUZZ_INIT();
|
||||
|
||||
void vuln(char *buf) {
|
||||
if(strcmp(buf, "vuln") == 0) {
|
||||
abort();
|
||||
}
|
||||
if (strcmp(buf, "vuln") == 0) { abort(); }
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
FILE *file = stdin;
|
||||
if (argc > 1) { file = fopen(argv[1], "rb"); }
|
||||
|
||||
int main(int argc, char **argv){
|
||||
// The following three lines are for normal fuzzing.
|
||||
/*
|
||||
char buf[16];
|
||||
char* p = fgets(buf, 16, file);
|
||||
buf[15] = 0;
|
||||
*/
|
||||
|
||||
FILE* file = stdin;
|
||||
if (argc > 1) {
|
||||
file = fopen(argv[1], "rb");
|
||||
// The following line is also needed for shared memory testcase fuzzing
|
||||
unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF;
|
||||
|
||||
printf("input: %s\n", buf);
|
||||
if (buf[0] == 'b') {
|
||||
if (buf[1] == 'a') {
|
||||
if (buf[2] == 'd') { abort(); }
|
||||
}
|
||||
}
|
||||
vuln(buf);
|
||||
|
||||
// The following three lines are for normal fuzzing.
|
||||
/*
|
||||
char buf[16];
|
||||
char* p = fgets(buf, 16, file);
|
||||
buf[15] = 0;
|
||||
*/
|
||||
|
||||
// The following line is also needed for shared memory testcase fuzzing
|
||||
unsigned char *buf = __AFL_FUZZ_TESTCASE_BUF;
|
||||
|
||||
|
||||
printf("input: %s\n", buf);
|
||||
if(buf[0] == 'b'){
|
||||
if(buf[1] == 'a'){
|
||||
if(buf[2] == 'd'){
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
vuln(buf);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -24,55 +24,54 @@
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
|
||||
#define PNG_CLEANUP \
|
||||
if(png_handler.png_ptr) \
|
||||
{ \
|
||||
if (png_handler.row_ptr) \
|
||||
png_free(png_handler.png_ptr, png_handler.row_ptr); \
|
||||
if (png_handler.end_info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr,\
|
||||
&png_handler.end_info_ptr); \
|
||||
else if (png_handler.info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr,\
|
||||
nullptr); \
|
||||
else \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, nullptr, nullptr); \
|
||||
png_handler.png_ptr = nullptr; \
|
||||
png_handler.row_ptr = nullptr; \
|
||||
png_handler.info_ptr = nullptr; \
|
||||
png_handler.end_info_ptr = nullptr; \
|
||||
#define PNG_CLEANUP \
|
||||
if (png_handler.png_ptr) { \
|
||||
if (png_handler.row_ptr) { \
|
||||
png_free(png_handler.png_ptr, png_handler.row_ptr); \
|
||||
} \
|
||||
if (png_handler.end_info_ptr) { \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr, \
|
||||
&png_handler.end_info_ptr); \
|
||||
} else if (png_handler.info_ptr) { \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr, \
|
||||
nullptr); \
|
||||
} else { \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, nullptr, nullptr); \
|
||||
} \
|
||||
png_handler.png_ptr = nullptr; \
|
||||
png_handler.row_ptr = nullptr; \
|
||||
png_handler.info_ptr = nullptr; \
|
||||
png_handler.end_info_ptr = nullptr; \
|
||||
}
|
||||
|
||||
struct BufState {
|
||||
const uint8_t* data;
|
||||
size_t bytes_left;
|
||||
const uint8_t *data;
|
||||
size_t bytes_left;
|
||||
};
|
||||
|
||||
struct PngObjectHandler {
|
||||
png_infop info_ptr = nullptr;
|
||||
png_infop info_ptr = nullptr;
|
||||
png_structp png_ptr = nullptr;
|
||||
png_infop end_info_ptr = nullptr;
|
||||
png_voidp row_ptr = nullptr;
|
||||
BufState* buf_state = nullptr;
|
||||
png_infop end_info_ptr = nullptr;
|
||||
png_voidp row_ptr = nullptr;
|
||||
BufState *buf_state = nullptr;
|
||||
|
||||
~PngObjectHandler() {
|
||||
if (row_ptr)
|
||||
png_free(png_ptr, row_ptr);
|
||||
if (end_info_ptr)
|
||||
if (row_ptr) { png_free(png_ptr, row_ptr); }
|
||||
if (end_info_ptr) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info_ptr);
|
||||
else if (info_ptr)
|
||||
} else if (info_ptr) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
|
||||
else
|
||||
} else {
|
||||
png_destroy_read_struct(&png_ptr, nullptr, nullptr);
|
||||
}
|
||||
delete buf_state;
|
||||
}
|
||||
};
|
||||
|
||||
void user_read_data(png_structp png_ptr, png_bytep data, size_t length) {
|
||||
BufState* buf_state = static_cast<BufState*>(png_get_io_ptr(png_ptr));
|
||||
if (length > buf_state->bytes_left) {
|
||||
png_error(png_ptr, "read error");
|
||||
}
|
||||
BufState *buf_state = static_cast<BufState *>(png_get_io_ptr(png_ptr));
|
||||
if (length > buf_state->bytes_left) { png_error(png_ptr, "read error"); }
|
||||
memcpy(data, buf_state->data, length);
|
||||
buf_state->bytes_left -= length;
|
||||
buf_state->data += length;
|
||||
@ -84,163 +83,153 @@ extern "C" int afl_libfuzzer_init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char * allocation = NULL;
|
||||
__attribute__((noinline))
|
||||
void func3( char * alloc) {
|
||||
//printf("func3\n");
|
||||
#ifdef _WIN32
|
||||
static char *allocation = NULL;
|
||||
|
||||
__attribute__((noinline)) void func3(char *alloc) {
|
||||
// printf("func3\n");
|
||||
#ifdef _WIN32
|
||||
if (rand() == 0) {
|
||||
alloc[0x1ff] = 0xde;
|
||||
printf("alloc[0x200]: %d\n", alloc[0x200]);
|
||||
}
|
||||
#else
|
||||
#else
|
||||
if (random() == 0) {
|
||||
alloc[0x1ff] = 0xde;
|
||||
printf("alloc[0x200]: %d\n", alloc[0x200]);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
__attribute__((noinline))
|
||||
void func2() {
|
||||
allocation = (char*)malloc(0xff);
|
||||
//printf("func2\n");
|
||||
__attribute__((noinline)) void func2() {
|
||||
allocation = (char *)malloc(0xff);
|
||||
// printf("func2\n");
|
||||
func3(allocation);
|
||||
}
|
||||
__attribute__((noinline))
|
||||
void func1() {
|
||||
//printf("func1\n");
|
||||
__attribute__((noinline)) void func1() {
|
||||
// printf("func1\n");
|
||||
func2();
|
||||
}
|
||||
|
||||
|
||||
// Export this symbol
|
||||
#ifdef _WIN32
|
||||
# define HARNESS_EXPORTS __declspec(dllexport)
|
||||
#define HARNESS_EXPORTS __declspec(dllexport)
|
||||
#else
|
||||
# define HARNESS_EXPORTS
|
||||
#define HARNESS_EXPORTS
|
||||
#endif
|
||||
|
||||
// Entry point for LibFuzzer.
|
||||
// Roughly follows the libpng book example:
|
||||
// http://www.libpng.org/pub/png/book/chapter13.html
|
||||
HARNESS_EXPORTS extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
|
||||
if (size >= 8 && *(uint64_t*)data == 0xABCDEFAA8F1324AA){
|
||||
abort();
|
||||
}
|
||||
if (size < kPngHeaderSize) {
|
||||
return 0;
|
||||
}
|
||||
HARNESS_EXPORTS extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data,
|
||||
size_t size) {
|
||||
if (size >= 8 && *(uint64_t *)data == 0xABCDEFAA8F1324AA) { abort(); }
|
||||
if (size < kPngHeaderSize) { return 0; }
|
||||
|
||||
#ifdef TEST_ASAN
|
||||
func1();
|
||||
func1();
|
||||
#endif
|
||||
|
||||
std::vector<unsigned char> v(data, data + size);
|
||||
if (png_sig_cmp(v.data(), 0, kPngHeaderSize)) {
|
||||
// not a PNG.
|
||||
return 0;
|
||||
}
|
||||
std::vector<unsigned char> v(data, data + size);
|
||||
if (png_sig_cmp(v.data(), 0, kPngHeaderSize)) {
|
||||
// not a PNG.
|
||||
return 0;
|
||||
}
|
||||
|
||||
PngObjectHandler png_handler;
|
||||
png_handler.png_ptr = nullptr;
|
||||
png_handler.row_ptr = nullptr;
|
||||
png_handler.info_ptr = nullptr;
|
||||
png_handler.end_info_ptr = nullptr;
|
||||
PngObjectHandler png_handler;
|
||||
png_handler.png_ptr = nullptr;
|
||||
png_handler.row_ptr = nullptr;
|
||||
png_handler.info_ptr = nullptr;
|
||||
png_handler.end_info_ptr = nullptr;
|
||||
|
||||
png_handler.png_ptr = png_create_read_struct
|
||||
(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!png_handler.png_ptr) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
png_handler.info_ptr = png_create_info_struct(png_handler.png_ptr);
|
||||
if (!png_handler.info_ptr) {
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
|
||||
png_handler.end_info_ptr = png_create_info_struct(png_handler.png_ptr);
|
||||
if (!png_handler.end_info_ptr) {
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
|
||||
png_set_crc_action(png_handler.png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE);
|
||||
#ifdef PNG_IGNORE_ADLER32
|
||||
png_set_option(png_handler.png_ptr, PNG_IGNORE_ADLER32, PNG_OPTION_ON);
|
||||
#endif
|
||||
|
||||
// Setting up reading from buffer.
|
||||
png_handler.buf_state = new BufState();
|
||||
png_handler.buf_state->data = data + kPngHeaderSize;
|
||||
png_handler.buf_state->bytes_left = size - kPngHeaderSize;
|
||||
png_set_read_fn(png_handler.png_ptr, png_handler.buf_state, user_read_data);
|
||||
png_set_sig_bytes(png_handler.png_ptr, kPngHeaderSize);
|
||||
|
||||
if (setjmp(png_jmpbuf(png_handler.png_ptr))) {
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Reading.
|
||||
png_read_info(png_handler.png_ptr, png_handler.info_ptr);
|
||||
|
||||
// reset error handler to put png_deleter into scope.
|
||||
if (setjmp(png_jmpbuf(png_handler.png_ptr))) {
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
|
||||
png_uint_32 width, height;
|
||||
int bit_depth, color_type, interlace_type, compression_type;
|
||||
int filter_type;
|
||||
|
||||
if (!png_get_IHDR(png_handler.png_ptr, png_handler.info_ptr, &width,
|
||||
&height, &bit_depth, &color_type, &interlace_type,
|
||||
&compression_type, &filter_type)) {
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This is going to be too slow.
|
||||
if (width && height > 100000000 / width) {
|
||||
PNG_CLEANUP
|
||||
#ifdef HAS_DUMMY_CRASH
|
||||
#ifdef __aarch64__
|
||||
asm volatile (".word 0xf7f0a000\n");
|
||||
#else
|
||||
asm("ud2");
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set several transforms that browsers typically use:
|
||||
png_set_gray_to_rgb(png_handler.png_ptr);
|
||||
png_set_expand(png_handler.png_ptr);
|
||||
png_set_packing(png_handler.png_ptr);
|
||||
png_set_scale_16(png_handler.png_ptr);
|
||||
png_set_tRNS_to_alpha(png_handler.png_ptr);
|
||||
|
||||
int passes = png_set_interlace_handling(png_handler.png_ptr);
|
||||
|
||||
png_read_update_info(png_handler.png_ptr, png_handler.info_ptr);
|
||||
|
||||
png_handler.row_ptr = png_malloc(
|
||||
png_handler.png_ptr, png_get_rowbytes(png_handler.png_ptr,
|
||||
png_handler.info_ptr));
|
||||
|
||||
for (int pass = 0; pass < passes; ++pass) {
|
||||
for (png_uint_32 y = 0; y < height; ++y) {
|
||||
png_read_row(png_handler.png_ptr,
|
||||
static_cast<png_bytep>(png_handler.row_ptr), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
png_read_end(png_handler.png_ptr, png_handler.end_info_ptr);
|
||||
png_handler.png_ptr =
|
||||
png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!png_handler.png_ptr) { return 0; }
|
||||
|
||||
png_handler.info_ptr = png_create_info_struct(png_handler.png_ptr);
|
||||
if (!png_handler.info_ptr) {
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
png_handler.end_info_ptr = png_create_info_struct(png_handler.png_ptr);
|
||||
if (!png_handler.end_info_ptr) {
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
|
||||
png_set_crc_action(png_handler.png_ptr, PNG_CRC_QUIET_USE, PNG_CRC_QUIET_USE);
|
||||
#ifdef PNG_IGNORE_ADLER32
|
||||
png_set_option(png_handler.png_ptr, PNG_IGNORE_ADLER32, PNG_OPTION_ON);
|
||||
#endif
|
||||
|
||||
// Setting up reading from buffer.
|
||||
png_handler.buf_state = new BufState();
|
||||
png_handler.buf_state->data = data + kPngHeaderSize;
|
||||
png_handler.buf_state->bytes_left = size - kPngHeaderSize;
|
||||
png_set_read_fn(png_handler.png_ptr, png_handler.buf_state, user_read_data);
|
||||
png_set_sig_bytes(png_handler.png_ptr, kPngHeaderSize);
|
||||
|
||||
if (setjmp(png_jmpbuf(png_handler.png_ptr))) {
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Reading.
|
||||
png_read_info(png_handler.png_ptr, png_handler.info_ptr);
|
||||
|
||||
// reset error handler to put png_deleter into scope.
|
||||
if (setjmp(png_jmpbuf(png_handler.png_ptr))) {
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
|
||||
png_uint_32 width, height;
|
||||
int bit_depth, color_type, interlace_type, compression_type;
|
||||
int filter_type;
|
||||
|
||||
if (!png_get_IHDR(png_handler.png_ptr, png_handler.info_ptr, &width, &height,
|
||||
&bit_depth, &color_type, &interlace_type, &compression_type,
|
||||
&filter_type)) {
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This is going to be too slow.
|
||||
if (width && height > 100000000 / width) {
|
||||
PNG_CLEANUP
|
||||
#ifdef HAS_DUMMY_CRASH
|
||||
#ifdef __aarch64__
|
||||
asm volatile(".word 0xf7f0a000\n");
|
||||
#else
|
||||
asm("ud2");
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Set several transforms that browsers typically use:
|
||||
png_set_gray_to_rgb(png_handler.png_ptr);
|
||||
png_set_expand(png_handler.png_ptr);
|
||||
png_set_packing(png_handler.png_ptr);
|
||||
png_set_scale_16(png_handler.png_ptr);
|
||||
png_set_tRNS_to_alpha(png_handler.png_ptr);
|
||||
|
||||
int passes = png_set_interlace_handling(png_handler.png_ptr);
|
||||
|
||||
png_read_update_info(png_handler.png_ptr, png_handler.info_ptr);
|
||||
|
||||
png_handler.row_ptr =
|
||||
png_malloc(png_handler.png_ptr,
|
||||
png_get_rowbytes(png_handler.png_ptr, png_handler.info_ptr));
|
||||
|
||||
for (int pass = 0; pass < passes; ++pass) {
|
||||
for (png_uint_32 y = 0; y < height; ++y) {
|
||||
png_read_row(png_handler.png_ptr,
|
||||
static_cast<png_bytep>(png_handler.row_ptr), nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
png_read_end(png_handler.png_ptr, png_handler.end_info_ptr);
|
||||
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
|
@ -2,8 +2,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
if (Size >= 8 && *(uint32_t*)Data == 0xaabbccdd)
|
||||
abort();
|
||||
if (Size >= 8 && *(uint32_t *)Data == 0xaabbccdd) { abort(); }
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -4,8 +4,6 @@
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
|
||||
|
||||
int main() {
|
||||
|
||||
char buf [10] = {0};
|
||||
char buf[10] = {0};
|
||||
LLVMFuzzerTestOneInput(buf, 10);
|
||||
|
||||
}
|
||||
|
@ -4,8 +4,6 @@
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
|
||||
|
||||
int main() {
|
||||
|
||||
char buf [10] = {0};
|
||||
char buf[10] = {0};
|
||||
LLVMFuzzerTestOneInput(buf, 10);
|
||||
|
||||
}
|
||||
|
@ -2,8 +2,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
if (Size >= 8 && *(uint32_t*)Data == 0xaabbccdd)
|
||||
abort();
|
||||
if (Size >= 8 && *(uint32_t *)Data == 0xaabbccdd) { abort(); }
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2,8 +2,7 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
if (Size >= 8 && *(uint32_t*)Data == 0xaabbccdd)
|
||||
abort();
|
||||
if (Size >= 8 && *(uint32_t *)Data == 0xaabbccdd) { abort(); }
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3,11 +3,10 @@
|
||||
#include <setjmp.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
struct my_error_mgr {
|
||||
struct jpeg_error_mgr pub; /* "public" fields */
|
||||
struct jpeg_error_mgr pub; /* "public" fields */
|
||||
|
||||
jmp_buf setjmp_buffer; /* for return to caller */
|
||||
jmp_buf setjmp_buffer; /* for return to caller */
|
||||
};
|
||||
|
||||
typedef struct my_error_mgr *my_error_ptr;
|
||||
@ -16,77 +15,67 @@ typedef struct my_error_mgr *my_error_ptr;
|
||||
* Here's the routine that will replace the standard error_exit method:
|
||||
*/
|
||||
|
||||
METHODDEF(void)
|
||||
my_error_exit(j_common_ptr cinfo)
|
||||
{
|
||||
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
|
||||
my_error_ptr myerr = (my_error_ptr)cinfo->err;
|
||||
METHODDEF(void)
|
||||
my_error_exit(j_common_ptr cinfo) {
|
||||
/* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
|
||||
my_error_ptr myerr = (my_error_ptr)cinfo->err;
|
||||
|
||||
/* Always display the message. */
|
||||
/* We could postpone this until after returning, if we chose. */
|
||||
(*cinfo->err->output_message) (cinfo);
|
||||
/* Always display the message. */
|
||||
/* We could postpone this until after returning, if we chose. */
|
||||
(*cinfo->err->output_message)(cinfo);
|
||||
|
||||
/* Return control to the setjmp point */
|
||||
longjmp(myerr->setjmp_buffer, 1);
|
||||
/* Return control to the setjmp point */
|
||||
longjmp(myerr->setjmp_buffer, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int do_read_JPEG_file(struct jpeg_decompress_struct *cinfo, const uint8_t *input, size_t len)
|
||||
{
|
||||
struct my_error_mgr jerr;
|
||||
/* More stuff */
|
||||
JSAMPARRAY buffer; /* Output row buffer */
|
||||
int row_stride; /* physical row width in output buffer */
|
||||
/* Step 1: allocate and initialize JPEG decompression object */
|
||||
/* We set up the normal JPEG error routines, then override error_exit. */
|
||||
cinfo->err = jpeg_std_error(&jerr.pub);
|
||||
jerr.pub.error_exit = my_error_exit;
|
||||
/* Establish the setjmp return context for my_error_exit to use. */
|
||||
if (setjmp(jerr.setjmp_buffer)) {
|
||||
jpeg_destroy_decompress(cinfo);
|
||||
return 0;
|
||||
}
|
||||
/* Now we can initialize the JPEG decompression object. */
|
||||
jpeg_create_decompress(cinfo);
|
||||
/* Step 2: specify data source (eg, a file) */
|
||||
jpeg_mem_src(cinfo,input, len );
|
||||
/* Step 3: read file parameters with jpeg_read_header() */
|
||||
(void)jpeg_read_header(cinfo, TRUE);
|
||||
/* Step 4: set parameters for decompression */
|
||||
/* In this example, we don't need to change any of the defaults set by
|
||||
* jpeg_read_header(), so we do nothing here.
|
||||
*/
|
||||
/* Step 5: Start decompressor */
|
||||
(void)jpeg_start_decompress(cinfo);
|
||||
/* JSAMPLEs per row in output buffer */
|
||||
row_stride = cinfo->output_width * cinfo->output_components;
|
||||
/* Make a one-row-high sample array that will go away when done with image */
|
||||
buffer = (*cinfo->mem->alloc_sarray)
|
||||
((j_common_ptr)cinfo, JPOOL_IMAGE, row_stride, 1);
|
||||
/* Step 6: while (scan lines remain to be read) */
|
||||
/* jpeg_read_scanlines(...); */
|
||||
while (cinfo->output_scanline < cinfo->output_height) {
|
||||
(void)jpeg_read_scanlines(cinfo, buffer, 1);
|
||||
/* Assume put_scanline_someplace wants a pointer and sample count. */
|
||||
//put_scanline_someplace(buffer[0], row_stride);
|
||||
}
|
||||
/* Step 7: Finish decompression */
|
||||
(void)jpeg_finish_decompress(cinfo);
|
||||
/* Step 8: Release JPEG decompression object */
|
||||
//jpeg_destroy_decompress(cinfo);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
|
||||
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
do_read_JPEG_file(&cinfo,data,size);
|
||||
int do_read_JPEG_file(struct jpeg_decompress_struct *cinfo,
|
||||
const uint8_t *input, size_t len) {
|
||||
struct my_error_mgr jerr;
|
||||
/* More stuff */
|
||||
JSAMPARRAY buffer; /* Output row buffer */
|
||||
int row_stride; /* physical row width in output buffer */
|
||||
/* Step 1: allocate and initialize JPEG decompression object */
|
||||
/* We set up the normal JPEG error routines, then override error_exit. */
|
||||
cinfo->err = jpeg_std_error(&jerr.pub);
|
||||
jerr.pub.error_exit = my_error_exit;
|
||||
/* Establish the setjmp return context for my_error_exit to use. */
|
||||
if (setjmp(jerr.setjmp_buffer)) {
|
||||
jpeg_destroy_decompress(cinfo);
|
||||
return 0;
|
||||
|
||||
}
|
||||
/* Now we can initialize the JPEG decompression object. */
|
||||
jpeg_create_decompress(cinfo);
|
||||
/* Step 2: specify data source (eg, a file) */
|
||||
jpeg_mem_src(cinfo, input, len);
|
||||
/* Step 3: read file parameters with jpeg_read_header() */
|
||||
(void)jpeg_read_header(cinfo, TRUE);
|
||||
/* Step 4: set parameters for decompression */
|
||||
/* In this example, we don't need to change any of the defaults set by
|
||||
* jpeg_read_header(), so we do nothing here.
|
||||
*/
|
||||
/* Step 5: Start decompressor */
|
||||
(void)jpeg_start_decompress(cinfo);
|
||||
/* JSAMPLEs per row in output buffer */
|
||||
row_stride = cinfo->output_width * cinfo->output_components;
|
||||
/* Make a one-row-high sample array that will go away when done with image */
|
||||
buffer = (*cinfo->mem->alloc_sarray)((j_common_ptr)cinfo, JPOOL_IMAGE,
|
||||
row_stride, 1);
|
||||
/* Step 6: while (scan lines remain to be read) */
|
||||
/* jpeg_read_scanlines(...); */
|
||||
while (cinfo->output_scanline < cinfo->output_height) {
|
||||
(void)jpeg_read_scanlines(cinfo, buffer, 1);
|
||||
/* Assume put_scanline_someplace wants a pointer and sample count. */
|
||||
// put_scanline_someplace(buffer[0], row_stride);
|
||||
}
|
||||
/* Step 7: Finish decompression */
|
||||
(void)jpeg_finish_decompress(cinfo);
|
||||
/* Step 8: Release JPEG decompression object */
|
||||
// jpeg_destroy_decompress(cinfo);
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
do_read_JPEG_file(&cinfo, data, size);
|
||||
return 0;
|
||||
}
|
||||
|
@ -2,32 +2,30 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAP_SIZE (16*1024)
|
||||
#define MAP_SIZE (16 * 1024)
|
||||
|
||||
#ifdef _WIN32
|
||||
#define posix_memalign(p, a, s) (((*(p)) = _aligned_malloc((s), (a))), *(p) ?0 :errno)
|
||||
#define RETADDR (uintptr_t)_ReturnAddress()
|
||||
#define posix_memalign(p, a, s) \
|
||||
(((*(p)) = _aligned_malloc((s), (a))), *(p) ? 0 : errno)
|
||||
#define RETADDR (uintptr_t) _ReturnAddress()
|
||||
#else
|
||||
#define RETADDR (uintptr_t)__builtin_return_address(0)
|
||||
#define RETADDR (uintptr_t) __builtin_return_address(0)
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define MAX(a, b) \
|
||||
({ \
|
||||
\
|
||||
__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a > _b ? _a : _b; \
|
||||
\
|
||||
})
|
||||
#define MAX(a, b) \
|
||||
({ \
|
||||
__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a > _b ? _a : _b; \
|
||||
})
|
||||
#else
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
size_t libafl_alloc_map[MAP_SIZE];
|
||||
|
||||
void *malloc(size_t size) {
|
||||
|
||||
uintptr_t k = RETADDR;
|
||||
k = (k >> 4) ^ (k << 8);
|
||||
k &= MAP_SIZE - 1;
|
||||
@ -37,15 +35,11 @@ void *malloc(size_t size) {
|
||||
// Hence, even realloc(NULL, size) would loop in an optimized build.
|
||||
// We fall back to a stricter allocation function. Fingers crossed.
|
||||
void *ret = NULL;
|
||||
if (posix_memalign(&ret, 1<<6, size) != 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (posix_memalign(&ret, 1 << 6, size) != 0) { return NULL; }
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
void *calloc(size_t nmemb, size_t size) {
|
||||
|
||||
size *= nmemb;
|
||||
|
||||
uintptr_t k = RETADDR;
|
||||
@ -54,9 +48,6 @@ void *calloc(size_t nmemb, size_t size) {
|
||||
libafl_alloc_map[k] = MAX(libafl_alloc_map[k], size);
|
||||
|
||||
void *ret = NULL;
|
||||
if (posix_memalign(&ret, 1<<6, size) != 0) {
|
||||
return NULL;
|
||||
};
|
||||
if (posix_memalign(&ret, 1 << 6, size) != 0) { return NULL; };
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
@ -23,55 +23,54 @@
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
|
||||
#define PNG_CLEANUP \
|
||||
if(png_handler.png_ptr) \
|
||||
{ \
|
||||
if (png_handler.row_ptr) \
|
||||
png_free(png_handler.png_ptr, png_handler.row_ptr); \
|
||||
if (png_handler.end_info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr,\
|
||||
&png_handler.end_info_ptr); \
|
||||
else if (png_handler.info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr,\
|
||||
nullptr); \
|
||||
else \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, nullptr, nullptr); \
|
||||
png_handler.png_ptr = nullptr; \
|
||||
png_handler.row_ptr = nullptr; \
|
||||
png_handler.info_ptr = nullptr; \
|
||||
png_handler.end_info_ptr = nullptr; \
|
||||
#define PNG_CLEANUP \
|
||||
if (png_handler.png_ptr) { \
|
||||
if (png_handler.row_ptr) { \
|
||||
png_free(png_handler.png_ptr, png_handler.row_ptr); \
|
||||
} \
|
||||
if (png_handler.end_info_ptr) { \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr, \
|
||||
&png_handler.end_info_ptr); \
|
||||
} else if (png_handler.info_ptr) { \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr, \
|
||||
nullptr); \
|
||||
} else { \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, nullptr, nullptr); \
|
||||
} \
|
||||
png_handler.png_ptr = nullptr; \
|
||||
png_handler.row_ptr = nullptr; \
|
||||
png_handler.info_ptr = nullptr; \
|
||||
png_handler.end_info_ptr = nullptr; \
|
||||
}
|
||||
|
||||
struct BufState {
|
||||
const uint8_t* data;
|
||||
size_t bytes_left;
|
||||
const uint8_t *data;
|
||||
size_t bytes_left;
|
||||
};
|
||||
|
||||
struct PngObjectHandler {
|
||||
png_infop info_ptr = nullptr;
|
||||
png_infop info_ptr = nullptr;
|
||||
png_structp png_ptr = nullptr;
|
||||
png_infop end_info_ptr = nullptr;
|
||||
png_voidp row_ptr = nullptr;
|
||||
BufState* buf_state = nullptr;
|
||||
png_infop end_info_ptr = nullptr;
|
||||
png_voidp row_ptr = nullptr;
|
||||
BufState *buf_state = nullptr;
|
||||
|
||||
~PngObjectHandler() {
|
||||
if (row_ptr)
|
||||
png_free(png_ptr, row_ptr);
|
||||
if (end_info_ptr)
|
||||
if (row_ptr) { png_free(png_ptr, row_ptr); }
|
||||
if (end_info_ptr) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info_ptr);
|
||||
else if (info_ptr)
|
||||
} else if (info_ptr) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
|
||||
else
|
||||
} else {
|
||||
png_destroy_read_struct(&png_ptr, nullptr, nullptr);
|
||||
}
|
||||
delete buf_state;
|
||||
}
|
||||
};
|
||||
|
||||
void user_read_data(png_structp png_ptr, png_bytep data, size_t length) {
|
||||
BufState* buf_state = static_cast<BufState*>(png_get_io_ptr(png_ptr));
|
||||
if (length > buf_state->bytes_left) {
|
||||
png_error(png_ptr, "read error");
|
||||
}
|
||||
BufState *buf_state = static_cast<BufState *>(png_get_io_ptr(png_ptr));
|
||||
if (length > buf_state->bytes_left) { png_error(png_ptr, "read error"); }
|
||||
memcpy(data, buf_state->data, length);
|
||||
buf_state->bytes_left -= length;
|
||||
buf_state->data += length;
|
||||
@ -82,10 +81,8 @@ static const int kPngHeaderSize = 8;
|
||||
// Entry point for LibFuzzer.
|
||||
// Roughly follows the libpng book example:
|
||||
// http://www.libpng.org/pub/png/book/chapter13.html
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (size < kPngHeaderSize) {
|
||||
return 0;
|
||||
}
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
if (size < kPngHeaderSize) { return 0; }
|
||||
|
||||
std::vector<unsigned char> v(data, data + size);
|
||||
if (png_sig_cmp(v.data(), 0, kPngHeaderSize)) {
|
||||
@ -99,11 +96,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
png_handler.info_ptr = nullptr;
|
||||
png_handler.end_info_ptr = nullptr;
|
||||
|
||||
png_handler.png_ptr = png_create_read_struct
|
||||
(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!png_handler.png_ptr) {
|
||||
return 0;
|
||||
}
|
||||
png_handler.png_ptr =
|
||||
png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!png_handler.png_ptr) { return 0; }
|
||||
|
||||
png_handler.info_ptr = png_create_info_struct(png_handler.png_ptr);
|
||||
if (!png_handler.info_ptr) {
|
||||
@ -144,12 +139,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
}
|
||||
|
||||
png_uint_32 width, height;
|
||||
int bit_depth, color_type, interlace_type, compression_type;
|
||||
int filter_type;
|
||||
int bit_depth, color_type, interlace_type, compression_type;
|
||||
int filter_type;
|
||||
|
||||
if (!png_get_IHDR(png_handler.png_ptr, png_handler.info_ptr, &width,
|
||||
&height, &bit_depth, &color_type, &interlace_type,
|
||||
&compression_type, &filter_type)) {
|
||||
if (!png_get_IHDR(png_handler.png_ptr, png_handler.info_ptr, &width, &height,
|
||||
&bit_depth, &color_type, &interlace_type, &compression_type,
|
||||
&filter_type)) {
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
@ -158,11 +153,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (width && height > 100000000 / width) {
|
||||
PNG_CLEANUP
|
||||
#ifdef HAS_DUMMY_CRASH
|
||||
#ifdef __aarch64__
|
||||
asm volatile (".word 0xf7f0a000\n");
|
||||
#else
|
||||
asm("ud2");
|
||||
#endif
|
||||
#ifdef __aarch64__
|
||||
asm volatile(".word 0xf7f0a000\n");
|
||||
#else
|
||||
asm("ud2");
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@ -178,9 +173,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
|
||||
png_read_update_info(png_handler.png_ptr, png_handler.info_ptr);
|
||||
|
||||
png_handler.row_ptr = png_malloc(
|
||||
png_handler.png_ptr, png_get_rowbytes(png_handler.png_ptr,
|
||||
png_handler.info_ptr));
|
||||
png_handler.row_ptr =
|
||||
png_malloc(png_handler.png_ptr,
|
||||
png_get_rowbytes(png_handler.png_ptr, png_handler.info_ptr));
|
||||
|
||||
for (int pass = 0; pass < passes; ++pass) {
|
||||
for (png_uint_32 y = 0; y < height; ++y) {
|
||||
@ -194,4 +189,3 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -23,55 +23,54 @@
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
|
||||
#define PNG_CLEANUP \
|
||||
if(png_handler.png_ptr) \
|
||||
{ \
|
||||
if (png_handler.row_ptr) \
|
||||
png_free(png_handler.png_ptr, png_handler.row_ptr); \
|
||||
if (png_handler.end_info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr,\
|
||||
&png_handler.end_info_ptr); \
|
||||
else if (png_handler.info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr,\
|
||||
nullptr); \
|
||||
else \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, nullptr, nullptr); \
|
||||
png_handler.png_ptr = nullptr; \
|
||||
png_handler.row_ptr = nullptr; \
|
||||
png_handler.info_ptr = nullptr; \
|
||||
png_handler.end_info_ptr = nullptr; \
|
||||
#define PNG_CLEANUP \
|
||||
if (png_handler.png_ptr) { \
|
||||
if (png_handler.row_ptr) { \
|
||||
png_free(png_handler.png_ptr, png_handler.row_ptr); \
|
||||
} \
|
||||
if (png_handler.end_info_ptr) { \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr, \
|
||||
&png_handler.end_info_ptr); \
|
||||
} else if (png_handler.info_ptr) { \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr, \
|
||||
nullptr); \
|
||||
} else { \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, nullptr, nullptr); \
|
||||
} \
|
||||
png_handler.png_ptr = nullptr; \
|
||||
png_handler.row_ptr = nullptr; \
|
||||
png_handler.info_ptr = nullptr; \
|
||||
png_handler.end_info_ptr = nullptr; \
|
||||
}
|
||||
|
||||
struct BufState {
|
||||
const uint8_t* data;
|
||||
size_t bytes_left;
|
||||
const uint8_t *data;
|
||||
size_t bytes_left;
|
||||
};
|
||||
|
||||
struct PngObjectHandler {
|
||||
png_infop info_ptr = nullptr;
|
||||
png_infop info_ptr = nullptr;
|
||||
png_structp png_ptr = nullptr;
|
||||
png_infop end_info_ptr = nullptr;
|
||||
png_voidp row_ptr = nullptr;
|
||||
BufState* buf_state = nullptr;
|
||||
png_infop end_info_ptr = nullptr;
|
||||
png_voidp row_ptr = nullptr;
|
||||
BufState *buf_state = nullptr;
|
||||
|
||||
~PngObjectHandler() {
|
||||
if (row_ptr)
|
||||
png_free(png_ptr, row_ptr);
|
||||
if (end_info_ptr)
|
||||
if (row_ptr) { png_free(png_ptr, row_ptr); }
|
||||
if (end_info_ptr) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info_ptr);
|
||||
else if (info_ptr)
|
||||
} else if (info_ptr) {
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, nullptr);
|
||||
else
|
||||
} else {
|
||||
png_destroy_read_struct(&png_ptr, nullptr, nullptr);
|
||||
}
|
||||
delete buf_state;
|
||||
}
|
||||
};
|
||||
|
||||
void user_read_data(png_structp png_ptr, png_bytep data, size_t length) {
|
||||
BufState* buf_state = static_cast<BufState*>(png_get_io_ptr(png_ptr));
|
||||
if (length > buf_state->bytes_left) {
|
||||
png_error(png_ptr, "read error");
|
||||
}
|
||||
BufState *buf_state = static_cast<BufState *>(png_get_io_ptr(png_ptr));
|
||||
if (length > buf_state->bytes_left) { png_error(png_ptr, "read error"); }
|
||||
memcpy(data, buf_state->data, length);
|
||||
buf_state->bytes_left -= length;
|
||||
buf_state->data += length;
|
||||
@ -82,10 +81,8 @@ static const int kPngHeaderSize = 8;
|
||||
// Entry point for LibFuzzer.
|
||||
// Roughly follows the libpng book example:
|
||||
// http://www.libpng.org/pub/png/book/chapter13.html
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (size < kPngHeaderSize) {
|
||||
return 0;
|
||||
}
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
if (size < kPngHeaderSize) { return 0; }
|
||||
|
||||
std::vector<unsigned char> v(data, data + size);
|
||||
if (png_sig_cmp(v.data(), 0, kPngHeaderSize)) {
|
||||
@ -99,11 +96,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
png_handler.info_ptr = nullptr;
|
||||
png_handler.end_info_ptr = nullptr;
|
||||
|
||||
png_handler.png_ptr = png_create_read_struct
|
||||
(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!png_handler.png_ptr) {
|
||||
return 0;
|
||||
}
|
||||
png_handler.png_ptr =
|
||||
png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!png_handler.png_ptr) { return 0; }
|
||||
|
||||
png_handler.info_ptr = png_create_info_struct(png_handler.png_ptr);
|
||||
if (!png_handler.info_ptr) {
|
||||
@ -144,12 +139,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
}
|
||||
|
||||
png_uint_32 width, height;
|
||||
int bit_depth, color_type, interlace_type, compression_type;
|
||||
int filter_type;
|
||||
int bit_depth, color_type, interlace_type, compression_type;
|
||||
int filter_type;
|
||||
|
||||
if (!png_get_IHDR(png_handler.png_ptr, png_handler.info_ptr, &width,
|
||||
&height, &bit_depth, &color_type, &interlace_type,
|
||||
&compression_type, &filter_type)) {
|
||||
if (!png_get_IHDR(png_handler.png_ptr, png_handler.info_ptr, &width, &height,
|
||||
&bit_depth, &color_type, &interlace_type, &compression_type,
|
||||
&filter_type)) {
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
@ -158,11 +153,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (width && height > 100000000 / width) {
|
||||
PNG_CLEANUP
|
||||
#ifdef HAS_DUMMY_CRASH
|
||||
#ifdef __aarch64__
|
||||
asm volatile (".word 0xf7f0a000\n");
|
||||
#else
|
||||
asm("ud2");
|
||||
#endif
|
||||
#ifdef __aarch64__
|
||||
asm volatile(".word 0xf7f0a000\n");
|
||||
#else
|
||||
asm("ud2");
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@ -178,9 +173,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
|
||||
png_read_update_info(png_handler.png_ptr, png_handler.info_ptr);
|
||||
|
||||
png_handler.row_ptr = png_malloc(
|
||||
png_handler.png_ptr, png_get_rowbytes(png_handler.png_ptr,
|
||||
png_handler.info_ptr));
|
||||
png_handler.row_ptr =
|
||||
png_malloc(png_handler.png_ptr,
|
||||
png_get_rowbytes(png_handler.png_ptr, png_handler.info_ptr));
|
||||
|
||||
for (int pass = 0; pass < passes; ++pass) {
|
||||
for (png_uint_32 y = 0; y < height; ++y) {
|
||||
@ -194,4 +189,3 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -23,40 +23,38 @@
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
|
||||
#define PNG_CLEANUP \
|
||||
if(png_handler.png_ptr) \
|
||||
{ \
|
||||
if (png_handler.row_ptr) \
|
||||
png_free(png_handler.png_ptr, png_handler.row_ptr); \
|
||||
if (png_handler.end_info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr,\
|
||||
&png_handler.end_info_ptr); \
|
||||
else if (png_handler.info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr,\
|
||||
nullptr); \
|
||||
else \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, nullptr, nullptr); \
|
||||
png_handler.png_ptr = nullptr; \
|
||||
png_handler.row_ptr = nullptr; \
|
||||
png_handler.info_ptr = nullptr; \
|
||||
png_handler.end_info_ptr = nullptr; \
|
||||
#define PNG_CLEANUP \
|
||||
if (png_handler.png_ptr) { \
|
||||
if (png_handler.row_ptr) \
|
||||
png_free(png_handler.png_ptr, png_handler.row_ptr); \
|
||||
if (png_handler.end_info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr, \
|
||||
&png_handler.end_info_ptr); \
|
||||
else if (png_handler.info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr, \
|
||||
nullptr); \
|
||||
else \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, nullptr, nullptr); \
|
||||
png_handler.png_ptr = nullptr; \
|
||||
png_handler.row_ptr = nullptr; \
|
||||
png_handler.info_ptr = nullptr; \
|
||||
png_handler.end_info_ptr = nullptr; \
|
||||
}
|
||||
|
||||
struct BufState {
|
||||
const uint8_t* data;
|
||||
size_t bytes_left;
|
||||
const uint8_t *data;
|
||||
size_t bytes_left;
|
||||
};
|
||||
|
||||
struct PngObjectHandler {
|
||||
png_infop info_ptr = nullptr;
|
||||
png_infop info_ptr = nullptr;
|
||||
png_structp png_ptr = nullptr;
|
||||
png_infop end_info_ptr = nullptr;
|
||||
png_voidp row_ptr = nullptr;
|
||||
BufState* buf_state = nullptr;
|
||||
png_infop end_info_ptr = nullptr;
|
||||
png_voidp row_ptr = nullptr;
|
||||
BufState *buf_state = nullptr;
|
||||
|
||||
~PngObjectHandler() {
|
||||
if (row_ptr)
|
||||
png_free(png_ptr, row_ptr);
|
||||
if (row_ptr) { png_free(png_ptr, row_ptr); }
|
||||
if (end_info_ptr)
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info_ptr);
|
||||
else if (info_ptr)
|
||||
@ -68,10 +66,8 @@ struct PngObjectHandler {
|
||||
};
|
||||
|
||||
void user_read_data(png_structp png_ptr, png_bytep data, size_t length) {
|
||||
BufState* buf_state = static_cast<BufState*>(png_get_io_ptr(png_ptr));
|
||||
if (length > buf_state->bytes_left) {
|
||||
png_error(png_ptr, "read error");
|
||||
}
|
||||
BufState *buf_state = static_cast<BufState *>(png_get_io_ptr(png_ptr));
|
||||
if (length > buf_state->bytes_left) { png_error(png_ptr, "read error"); }
|
||||
memcpy(data, buf_state->data, length);
|
||||
buf_state->bytes_left -= length;
|
||||
buf_state->data += length;
|
||||
@ -82,10 +78,8 @@ static const int kPngHeaderSize = 8;
|
||||
// Entry point for LibFuzzer.
|
||||
// Roughly follows the libpng book example:
|
||||
// http://www.libpng.org/pub/png/book/chapter13.html
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (size < kPngHeaderSize) {
|
||||
return 0;
|
||||
}
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
if (size < kPngHeaderSize) { return 0; }
|
||||
|
||||
std::vector<unsigned char> v(data, data + size);
|
||||
if (png_sig_cmp(v.data(), 0, kPngHeaderSize)) {
|
||||
@ -99,11 +93,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
png_handler.info_ptr = nullptr;
|
||||
png_handler.end_info_ptr = nullptr;
|
||||
|
||||
png_handler.png_ptr = png_create_read_struct
|
||||
(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!png_handler.png_ptr) {
|
||||
return 0;
|
||||
}
|
||||
png_handler.png_ptr =
|
||||
png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!png_handler.png_ptr) { return 0; }
|
||||
|
||||
png_handler.info_ptr = png_create_info_struct(png_handler.png_ptr);
|
||||
if (!png_handler.info_ptr) {
|
||||
@ -144,12 +136,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
}
|
||||
|
||||
png_uint_32 width, height;
|
||||
int bit_depth, color_type, interlace_type, compression_type;
|
||||
int filter_type;
|
||||
int bit_depth, color_type, interlace_type, compression_type;
|
||||
int filter_type;
|
||||
|
||||
if (!png_get_IHDR(png_handler.png_ptr, png_handler.info_ptr, &width,
|
||||
&height, &bit_depth, &color_type, &interlace_type,
|
||||
&compression_type, &filter_type)) {
|
||||
if (!png_get_IHDR(png_handler.png_ptr, png_handler.info_ptr, &width, &height,
|
||||
&bit_depth, &color_type, &interlace_type, &compression_type,
|
||||
&filter_type)) {
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
@ -158,11 +150,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (width && height > 100000000 / width) {
|
||||
PNG_CLEANUP
|
||||
#ifdef HAS_DUMMY_CRASH
|
||||
#ifdef __aarch64__
|
||||
asm volatile (".word 0xf7f0a000\n");
|
||||
#else
|
||||
asm("ud2");
|
||||
#endif
|
||||
#ifdef __aarch64__
|
||||
asm volatile(".word 0xf7f0a000\n");
|
||||
#else
|
||||
asm("ud2");
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@ -178,9 +170,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
|
||||
png_read_update_info(png_handler.png_ptr, png_handler.info_ptr);
|
||||
|
||||
png_handler.row_ptr = png_malloc(
|
||||
png_handler.png_ptr, png_get_rowbytes(png_handler.png_ptr,
|
||||
png_handler.info_ptr));
|
||||
png_handler.row_ptr =
|
||||
png_malloc(png_handler.png_ptr,
|
||||
png_get_rowbytes(png_handler.png_ptr, png_handler.info_ptr));
|
||||
|
||||
for (int pass = 0; pass < passes; ++pass) {
|
||||
for (png_uint_32 y = 0; y < height; ++y) {
|
||||
@ -194,4 +186,3 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -23,40 +23,38 @@
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
|
||||
#define PNG_CLEANUP \
|
||||
if(png_handler.png_ptr) \
|
||||
{ \
|
||||
if (png_handler.row_ptr) \
|
||||
png_free(png_handler.png_ptr, png_handler.row_ptr); \
|
||||
if (png_handler.end_info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr,\
|
||||
&png_handler.end_info_ptr); \
|
||||
else if (png_handler.info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr,\
|
||||
nullptr); \
|
||||
else \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, nullptr, nullptr); \
|
||||
png_handler.png_ptr = nullptr; \
|
||||
png_handler.row_ptr = nullptr; \
|
||||
png_handler.info_ptr = nullptr; \
|
||||
png_handler.end_info_ptr = nullptr; \
|
||||
#define PNG_CLEANUP \
|
||||
if (png_handler.png_ptr) { \
|
||||
if (png_handler.row_ptr) \
|
||||
png_free(png_handler.png_ptr, png_handler.row_ptr); \
|
||||
if (png_handler.end_info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr, \
|
||||
&png_handler.end_info_ptr); \
|
||||
else if (png_handler.info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr, \
|
||||
nullptr); \
|
||||
else \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, nullptr, nullptr); \
|
||||
png_handler.png_ptr = nullptr; \
|
||||
png_handler.row_ptr = nullptr; \
|
||||
png_handler.info_ptr = nullptr; \
|
||||
png_handler.end_info_ptr = nullptr; \
|
||||
}
|
||||
|
||||
struct BufState {
|
||||
const uint8_t* data;
|
||||
size_t bytes_left;
|
||||
const uint8_t *data;
|
||||
size_t bytes_left;
|
||||
};
|
||||
|
||||
struct PngObjectHandler {
|
||||
png_infop info_ptr = nullptr;
|
||||
png_infop info_ptr = nullptr;
|
||||
png_structp png_ptr = nullptr;
|
||||
png_infop end_info_ptr = nullptr;
|
||||
png_voidp row_ptr = nullptr;
|
||||
BufState* buf_state = nullptr;
|
||||
png_infop end_info_ptr = nullptr;
|
||||
png_voidp row_ptr = nullptr;
|
||||
BufState *buf_state = nullptr;
|
||||
|
||||
~PngObjectHandler() {
|
||||
if (row_ptr)
|
||||
png_free(png_ptr, row_ptr);
|
||||
if (row_ptr) { png_free(png_ptr, row_ptr); }
|
||||
if (end_info_ptr)
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info_ptr);
|
||||
else if (info_ptr)
|
||||
@ -68,10 +66,8 @@ struct PngObjectHandler {
|
||||
};
|
||||
|
||||
void user_read_data(png_structp png_ptr, png_bytep data, size_t length) {
|
||||
BufState* buf_state = static_cast<BufState*>(png_get_io_ptr(png_ptr));
|
||||
if (length > buf_state->bytes_left) {
|
||||
png_error(png_ptr, "read error");
|
||||
}
|
||||
BufState *buf_state = static_cast<BufState *>(png_get_io_ptr(png_ptr));
|
||||
if (length > buf_state->bytes_left) { png_error(png_ptr, "read error"); }
|
||||
memcpy(data, buf_state->data, length);
|
||||
buf_state->bytes_left -= length;
|
||||
buf_state->data += length;
|
||||
@ -82,10 +78,8 @@ static const int kPngHeaderSize = 8;
|
||||
// Entry point for LibFuzzer.
|
||||
// Roughly follows the libpng book example:
|
||||
// http://www.libpng.org/pub/png/book/chapter13.html
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (size < kPngHeaderSize) {
|
||||
return 0;
|
||||
}
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
if (size < kPngHeaderSize) { return 0; }
|
||||
|
||||
std::vector<unsigned char> v(data, data + size);
|
||||
if (png_sig_cmp(v.data(), 0, kPngHeaderSize)) {
|
||||
@ -99,11 +93,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
png_handler.info_ptr = nullptr;
|
||||
png_handler.end_info_ptr = nullptr;
|
||||
|
||||
png_handler.png_ptr = png_create_read_struct
|
||||
(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!png_handler.png_ptr) {
|
||||
return 0;
|
||||
}
|
||||
png_handler.png_ptr =
|
||||
png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!png_handler.png_ptr) { return 0; }
|
||||
|
||||
png_handler.info_ptr = png_create_info_struct(png_handler.png_ptr);
|
||||
if (!png_handler.info_ptr) {
|
||||
@ -144,12 +136,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
}
|
||||
|
||||
png_uint_32 width, height;
|
||||
int bit_depth, color_type, interlace_type, compression_type;
|
||||
int filter_type;
|
||||
int bit_depth, color_type, interlace_type, compression_type;
|
||||
int filter_type;
|
||||
|
||||
if (!png_get_IHDR(png_handler.png_ptr, png_handler.info_ptr, &width,
|
||||
&height, &bit_depth, &color_type, &interlace_type,
|
||||
&compression_type, &filter_type)) {
|
||||
if (!png_get_IHDR(png_handler.png_ptr, png_handler.info_ptr, &width, &height,
|
||||
&bit_depth, &color_type, &interlace_type, &compression_type,
|
||||
&filter_type)) {
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
@ -158,11 +150,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (width && height > 100000000 / width) {
|
||||
PNG_CLEANUP
|
||||
#ifdef HAS_DUMMY_CRASH
|
||||
#ifdef __aarch64__
|
||||
asm volatile (".word 0xf7f0a000\n");
|
||||
#else
|
||||
asm("ud2");
|
||||
#endif
|
||||
#ifdef __aarch64__
|
||||
asm volatile(".word 0xf7f0a000\n");
|
||||
#else
|
||||
asm("ud2");
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@ -178,9 +170,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
|
||||
png_read_update_info(png_handler.png_ptr, png_handler.info_ptr);
|
||||
|
||||
png_handler.row_ptr = png_malloc(
|
||||
png_handler.png_ptr, png_get_rowbytes(png_handler.png_ptr,
|
||||
png_handler.info_ptr));
|
||||
png_handler.row_ptr =
|
||||
png_malloc(png_handler.png_ptr,
|
||||
png_get_rowbytes(png_handler.png_ptr, png_handler.info_ptr));
|
||||
|
||||
for (int pass = 0; pass < passes; ++pass) {
|
||||
for (png_uint_32 y = 0; y < height; ++y) {
|
||||
@ -194,4 +186,3 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -23,40 +23,38 @@
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
|
||||
#define PNG_CLEANUP \
|
||||
if(png_handler.png_ptr) \
|
||||
{ \
|
||||
if (png_handler.row_ptr) \
|
||||
png_free(png_handler.png_ptr, png_handler.row_ptr); \
|
||||
if (png_handler.end_info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr,\
|
||||
&png_handler.end_info_ptr); \
|
||||
else if (png_handler.info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr,\
|
||||
nullptr); \
|
||||
else \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, nullptr, nullptr); \
|
||||
png_handler.png_ptr = nullptr; \
|
||||
png_handler.row_ptr = nullptr; \
|
||||
png_handler.info_ptr = nullptr; \
|
||||
png_handler.end_info_ptr = nullptr; \
|
||||
#define PNG_CLEANUP \
|
||||
if (png_handler.png_ptr) { \
|
||||
if (png_handler.row_ptr) \
|
||||
png_free(png_handler.png_ptr, png_handler.row_ptr); \
|
||||
if (png_handler.end_info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr, \
|
||||
&png_handler.end_info_ptr); \
|
||||
else if (png_handler.info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr, \
|
||||
nullptr); \
|
||||
else \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, nullptr, nullptr); \
|
||||
png_handler.png_ptr = nullptr; \
|
||||
png_handler.row_ptr = nullptr; \
|
||||
png_handler.info_ptr = nullptr; \
|
||||
png_handler.end_info_ptr = nullptr; \
|
||||
}
|
||||
|
||||
struct BufState {
|
||||
const uint8_t* data;
|
||||
size_t bytes_left;
|
||||
const uint8_t *data;
|
||||
size_t bytes_left;
|
||||
};
|
||||
|
||||
struct PngObjectHandler {
|
||||
png_infop info_ptr = nullptr;
|
||||
png_infop info_ptr = nullptr;
|
||||
png_structp png_ptr = nullptr;
|
||||
png_infop end_info_ptr = nullptr;
|
||||
png_voidp row_ptr = nullptr;
|
||||
BufState* buf_state = nullptr;
|
||||
png_infop end_info_ptr = nullptr;
|
||||
png_voidp row_ptr = nullptr;
|
||||
BufState *buf_state = nullptr;
|
||||
|
||||
~PngObjectHandler() {
|
||||
if (row_ptr)
|
||||
png_free(png_ptr, row_ptr);
|
||||
if (row_ptr) { png_free(png_ptr, row_ptr); }
|
||||
if (end_info_ptr)
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info_ptr);
|
||||
else if (info_ptr)
|
||||
@ -68,10 +66,8 @@ struct PngObjectHandler {
|
||||
};
|
||||
|
||||
void user_read_data(png_structp png_ptr, png_bytep data, size_t length) {
|
||||
BufState* buf_state = static_cast<BufState*>(png_get_io_ptr(png_ptr));
|
||||
if (length > buf_state->bytes_left) {
|
||||
png_error(png_ptr, "read error");
|
||||
}
|
||||
BufState *buf_state = static_cast<BufState *>(png_get_io_ptr(png_ptr));
|
||||
if (length > buf_state->bytes_left) { png_error(png_ptr, "read error"); }
|
||||
memcpy(data, buf_state->data, length);
|
||||
buf_state->bytes_left -= length;
|
||||
buf_state->data += length;
|
||||
@ -82,10 +78,8 @@ static const int kPngHeaderSize = 8;
|
||||
// Entry point for LibFuzzer.
|
||||
// Roughly follows the libpng book example:
|
||||
// http://www.libpng.org/pub/png/book/chapter13.html
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (size < kPngHeaderSize) {
|
||||
return 0;
|
||||
}
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
if (size < kPngHeaderSize) { return 0; }
|
||||
|
||||
std::vector<unsigned char> v(data, data + size);
|
||||
if (png_sig_cmp(v.data(), 0, kPngHeaderSize)) {
|
||||
@ -99,11 +93,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
png_handler.info_ptr = nullptr;
|
||||
png_handler.end_info_ptr = nullptr;
|
||||
|
||||
png_handler.png_ptr = png_create_read_struct
|
||||
(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!png_handler.png_ptr) {
|
||||
return 0;
|
||||
}
|
||||
png_handler.png_ptr =
|
||||
png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!png_handler.png_ptr) { return 0; }
|
||||
|
||||
png_handler.info_ptr = png_create_info_struct(png_handler.png_ptr);
|
||||
if (!png_handler.info_ptr) {
|
||||
@ -144,12 +136,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
}
|
||||
|
||||
png_uint_32 width, height;
|
||||
int bit_depth, color_type, interlace_type, compression_type;
|
||||
int filter_type;
|
||||
int bit_depth, color_type, interlace_type, compression_type;
|
||||
int filter_type;
|
||||
|
||||
if (!png_get_IHDR(png_handler.png_ptr, png_handler.info_ptr, &width,
|
||||
&height, &bit_depth, &color_type, &interlace_type,
|
||||
&compression_type, &filter_type)) {
|
||||
if (!png_get_IHDR(png_handler.png_ptr, png_handler.info_ptr, &width, &height,
|
||||
&bit_depth, &color_type, &interlace_type, &compression_type,
|
||||
&filter_type)) {
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
@ -158,11 +150,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (width && height > 100000000 / width) {
|
||||
PNG_CLEANUP
|
||||
#ifdef HAS_DUMMY_CRASH
|
||||
#ifdef __aarch64__
|
||||
asm volatile (".word 0xf7f0a000\n");
|
||||
#else
|
||||
asm("ud2");
|
||||
#endif
|
||||
#ifdef __aarch64__
|
||||
asm volatile(".word 0xf7f0a000\n");
|
||||
#else
|
||||
asm("ud2");
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@ -178,9 +170,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
|
||||
png_read_update_info(png_handler.png_ptr, png_handler.info_ptr);
|
||||
|
||||
png_handler.row_ptr = png_malloc(
|
||||
png_handler.png_ptr, png_get_rowbytes(png_handler.png_ptr,
|
||||
png_handler.info_ptr));
|
||||
png_handler.row_ptr =
|
||||
png_malloc(png_handler.png_ptr,
|
||||
png_get_rowbytes(png_handler.png_ptr, png_handler.info_ptr));
|
||||
|
||||
for (int pass = 0; pass < passes; ++pass) {
|
||||
for (png_uint_32 y = 0; y < height; ++y) {
|
||||
@ -194,4 +186,3 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,2 @@
|
||||
#include<stddef.h>
|
||||
#include <stddef.h>
|
||||
__attribute__((weak, visibility("default"))) size_t *__libafl_target_list;
|
||||
|
||||
|
@ -9,20 +9,21 @@
|
||||
|
||||
#include "stb_image.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
|
||||
{
|
||||
int x, y, channels;
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
int x, y, channels;
|
||||
|
||||
if(!stbi_info_from_memory(data, size, &x, &y, &channels)) return 0;
|
||||
if (!stbi_info_from_memory(data, size, &x, &y, &channels)) {return 0;}
|
||||
|
||||
/* exit if the image is larger than ~80MB */
|
||||
if(y && x > (80000000 / 4) / y) return 0;
|
||||
/* exit if the image is larger than ~80MB */
|
||||
if (y && x > (80000000 / 4) / y){ return 0;}
|
||||
|
||||
unsigned char *img = stbi_load_from_memory(data, size, &x, &y, &channels, 4);
|
||||
unsigned char *img = stbi_load_from_memory(data, size, &x, &y, &channels, 4);
|
||||
|
||||
free(img);
|
||||
|
||||
// if (x > 10000) free(img); // free crash
|
||||
|
||||
return 0;
|
||||
// if (x > 10000) {free(img);} // free crash
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -9,20 +9,21 @@
|
||||
|
||||
#include "stb_image.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
|
||||
{
|
||||
int x, y, channels;
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
int x, y, channels;
|
||||
|
||||
if(!stbi_info_from_memory(data, size, &x, &y, &channels)) return 0;
|
||||
if (!stbi_info_from_memory(data, size, &x, &y, &channels)) { return 0; }
|
||||
|
||||
/* exit if the image is larger than ~80MB */
|
||||
if(y && x > (80000000 / 4) / y) return 0;
|
||||
/* exit if the image is larger than ~80MB */
|
||||
if (y && x > (80000000 / 4) / y) { return 0; }
|
||||
|
||||
unsigned char *img = stbi_load_from_memory(data, size, &x, &y, &channels, 4);
|
||||
unsigned char *img = stbi_load_from_memory(data, size, &x, &y, &channels, 4);
|
||||
|
||||
free(img);
|
||||
|
||||
// if (x > 10000) free(img); // free crash
|
||||
free(img);
|
||||
|
||||
return 0;
|
||||
// if (x > 10000) free(img); // free crash
|
||||
|
||||
// if (x > 10000) {free(img);} // free crash
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -14,26 +14,22 @@
|
||||
#include "stb_image.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
if (argc < 2) {
|
||||
return -1;
|
||||
}
|
||||
if (argc < 2) { return -1; }
|
||||
|
||||
char *file_path = argv[1];
|
||||
|
||||
int x, y, channels;
|
||||
|
||||
if (!stbi_info(file_path, &x, &y, &channels))
|
||||
return 0;
|
||||
if (!stbi_info(file_path, &x, &y, &channels)) { return 0; }
|
||||
|
||||
/* exit if the image is larger than ~80MB */
|
||||
if (y && x > (80000000 / 4) / y)
|
||||
return 0;
|
||||
if (y && x > (80000000 / 4) / y) { return 0; }
|
||||
|
||||
unsigned char *img = stbi_load(file_path, &x, &y, &channels, 4);
|
||||
|
||||
free(img);
|
||||
|
||||
// if (x > 10000) free(img); // free crash
|
||||
// if (x > 10000) {free(img);} // free crash
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -9,20 +9,21 @@
|
||||
|
||||
#include "stb_image.h"
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size)
|
||||
{
|
||||
int x, y, channels;
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
int x, y, channels;
|
||||
|
||||
if(!stbi_info_from_memory(data, size, &x, &y, &channels)) return 0;
|
||||
if (!stbi_info_from_memory(data, size, &x, &y, &channels)) { return 0; }
|
||||
|
||||
/* exit if the image is larger than ~80MB */
|
||||
if(y && x > (80000000 / 4) / y) return 0;
|
||||
/* exit if the image is larger than ~80MB */
|
||||
if (y && x > (80000000 / 4) / y) { return 0; }
|
||||
|
||||
unsigned char *img = stbi_load_from_memory(data, size, &x, &y, &channels, 4);
|
||||
unsigned char *img = stbi_load_from_memory(data, size, &x, &y, &channels, 4);
|
||||
|
||||
free(img);
|
||||
|
||||
// if (x > 10000) free(img); // free crash
|
||||
free(img);
|
||||
|
||||
return 0;
|
||||
// if (x > 10000) free(img); // free crash
|
||||
|
||||
// if (x > 10000) {free(img);} // free crash
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3,14 +3,11 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
|
||||
// printf("Got %ld bytes.\n", Size);
|
||||
if (Size >= 4 && *(uint32_t*)Data == 0xaabbccdd)
|
||||
abort();
|
||||
// printf("Got %ld bytes.\n", Size);
|
||||
if (Size >= 4 && *(uint32_t *)Data == 0xaabbccdd) { abort(); }
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
char buf [10] = {0};
|
||||
char buf[10] = {0};
|
||||
LLVMFuzzerTestOneInput(buf, 10);
|
||||
|
||||
}
|
||||
|
@ -23,40 +23,38 @@
|
||||
#define PNG_INTERNAL
|
||||
#include "png.h"
|
||||
|
||||
#define PNG_CLEANUP \
|
||||
if(png_handler.png_ptr) \
|
||||
{ \
|
||||
if (png_handler.row_ptr) \
|
||||
png_free(png_handler.png_ptr, png_handler.row_ptr); \
|
||||
if (png_handler.end_info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr,\
|
||||
&png_handler.end_info_ptr); \
|
||||
else if (png_handler.info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr,\
|
||||
nullptr); \
|
||||
else \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, nullptr, nullptr); \
|
||||
png_handler.png_ptr = nullptr; \
|
||||
png_handler.row_ptr = nullptr; \
|
||||
png_handler.info_ptr = nullptr; \
|
||||
png_handler.end_info_ptr = nullptr; \
|
||||
#define PNG_CLEANUP \
|
||||
if (png_handler.png_ptr) { \
|
||||
if (png_handler.row_ptr) \
|
||||
png_free(png_handler.png_ptr, png_handler.row_ptr); \
|
||||
if (png_handler.end_info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr, \
|
||||
&png_handler.end_info_ptr); \
|
||||
else if (png_handler.info_ptr) \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, &png_handler.info_ptr, \
|
||||
nullptr); \
|
||||
else \
|
||||
png_destroy_read_struct(&png_handler.png_ptr, nullptr, nullptr); \
|
||||
png_handler.png_ptr = nullptr; \
|
||||
png_handler.row_ptr = nullptr; \
|
||||
png_handler.info_ptr = nullptr; \
|
||||
png_handler.end_info_ptr = nullptr; \
|
||||
}
|
||||
|
||||
struct BufState {
|
||||
const uint8_t* data;
|
||||
size_t bytes_left;
|
||||
const uint8_t *data;
|
||||
size_t bytes_left;
|
||||
};
|
||||
|
||||
struct PngObjectHandler {
|
||||
png_infop info_ptr = nullptr;
|
||||
png_infop info_ptr = nullptr;
|
||||
png_structp png_ptr = nullptr;
|
||||
png_infop end_info_ptr = nullptr;
|
||||
png_voidp row_ptr = nullptr;
|
||||
BufState* buf_state = nullptr;
|
||||
png_infop end_info_ptr = nullptr;
|
||||
png_voidp row_ptr = nullptr;
|
||||
BufState *buf_state = nullptr;
|
||||
|
||||
~PngObjectHandler() {
|
||||
if (row_ptr)
|
||||
png_free(png_ptr, row_ptr);
|
||||
if (row_ptr) { png_free(png_ptr, row_ptr); }
|
||||
if (end_info_ptr)
|
||||
png_destroy_read_struct(&png_ptr, &info_ptr, &end_info_ptr);
|
||||
else if (info_ptr)
|
||||
@ -68,10 +66,8 @@ struct PngObjectHandler {
|
||||
};
|
||||
|
||||
void user_read_data(png_structp png_ptr, png_bytep data, size_t length) {
|
||||
BufState* buf_state = static_cast<BufState*>(png_get_io_ptr(png_ptr));
|
||||
if (length > buf_state->bytes_left) {
|
||||
png_error(png_ptr, "read error");
|
||||
}
|
||||
BufState *buf_state = static_cast<BufState *>(png_get_io_ptr(png_ptr));
|
||||
if (length > buf_state->bytes_left) { png_error(png_ptr, "read error"); }
|
||||
memcpy(data, buf_state->data, length);
|
||||
buf_state->bytes_left -= length;
|
||||
buf_state->data += length;
|
||||
@ -82,10 +78,8 @@ static const int kPngHeaderSize = 8;
|
||||
// Entry point for LibFuzzer.
|
||||
// Roughly follows the libpng book example:
|
||||
// http://www.libpng.org/pub/png/book/chapter13.html
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (size < kPngHeaderSize) {
|
||||
return 0;
|
||||
}
|
||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
if (size < kPngHeaderSize) { return 0; }
|
||||
|
||||
std::vector<unsigned char> v(data, data + size);
|
||||
if (png_sig_cmp(v.data(), 0, kPngHeaderSize)) {
|
||||
@ -99,11 +93,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
png_handler.info_ptr = nullptr;
|
||||
png_handler.end_info_ptr = nullptr;
|
||||
|
||||
png_handler.png_ptr = png_create_read_struct
|
||||
(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!png_handler.png_ptr) {
|
||||
return 0;
|
||||
}
|
||||
png_handler.png_ptr =
|
||||
png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (!png_handler.png_ptr) { return 0; }
|
||||
|
||||
png_handler.info_ptr = png_create_info_struct(png_handler.png_ptr);
|
||||
if (!png_handler.info_ptr) {
|
||||
@ -144,12 +136,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
}
|
||||
|
||||
png_uint_32 width, height;
|
||||
int bit_depth, color_type, interlace_type, compression_type;
|
||||
int filter_type;
|
||||
int bit_depth, color_type, interlace_type, compression_type;
|
||||
int filter_type;
|
||||
|
||||
if (!png_get_IHDR(png_handler.png_ptr, png_handler.info_ptr, &width,
|
||||
&height, &bit_depth, &color_type, &interlace_type,
|
||||
&compression_type, &filter_type)) {
|
||||
if (!png_get_IHDR(png_handler.png_ptr, png_handler.info_ptr, &width, &height,
|
||||
&bit_depth, &color_type, &interlace_type, &compression_type,
|
||||
&filter_type)) {
|
||||
PNG_CLEANUP
|
||||
return 0;
|
||||
}
|
||||
@ -158,11 +150,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (width && height > 100000000 / width) {
|
||||
PNG_CLEANUP
|
||||
#ifdef HAS_DUMMY_CRASH
|
||||
#ifdef __aarch64__
|
||||
asm volatile (".word 0xf7f0a000\n");
|
||||
#else
|
||||
asm("ud2");
|
||||
#endif
|
||||
#ifdef __aarch64__
|
||||
asm volatile(".word 0xf7f0a000\n");
|
||||
#else
|
||||
asm("ud2");
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@ -178,9 +170,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
|
||||
png_read_update_info(png_handler.png_ptr, png_handler.info_ptr);
|
||||
|
||||
png_handler.row_ptr = png_malloc(
|
||||
png_handler.png_ptr, png_get_rowbytes(png_handler.png_ptr,
|
||||
png_handler.info_ptr));
|
||||
png_handler.row_ptr =
|
||||
png_malloc(png_handler.png_ptr,
|
||||
png_get_rowbytes(png_handler.png_ptr, png_handler.info_ptr));
|
||||
|
||||
for (int pass = 0; pass < passes; ++pass) {
|
||||
for (png_uint_32 y = 0; y < height; ++y) {
|
||||
@ -196,8 +188,6 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
}
|
||||
|
||||
int main() {
|
||||
|
||||
uint8_t buf [10] = {0};
|
||||
uint8_t buf[10] = {0};
|
||||
LLVMFuzzerTestOneInput(buf, 10);
|
||||
|
||||
}
|
||||
|
@ -173,10 +173,11 @@ PreservedAnalyses AFLCoverage::run(Module &M, ModuleAnalysisManager &MAM) {
|
||||
#else
|
||||
bool AFLCoverage::runOnModule(Module &M) {
|
||||
#endif
|
||||
if (Ctx && DumpCFG)
|
||||
if (Ctx && DumpCFG) {
|
||||
FATAL(
|
||||
"Does not support dumping CFG with full context sensitive coverage "
|
||||
"enabled.");
|
||||
}
|
||||
LLVMContext &C = M.getContext();
|
||||
|
||||
IntegerType *Int8Ty = IntegerType::getInt8Ty(C);
|
||||
@ -201,9 +202,10 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) {
|
||||
|
||||
map_size = atoi(ptr);
|
||||
if (map_size < 8 || map_size > (1 << 29))
|
||||
if (map_size < 8 || map_size > (1 << 29)) {
|
||||
FATAL("illegal AFL_MAP_SIZE %u, must be between 2^3 and 2^30",
|
||||
map_size); if (map_size % 8) map_size = (((map_size >> 3) + 1) << 3);
|
||||
}
|
||||
map_size); if (map_size % 8) {map_size = (((map_size >> 3) + 1) << 3);}
|
||||
|
||||
}
|
||||
|
||||
@ -211,8 +213,9 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
|
||||
/* Decide instrumentation ratio */
|
||||
|
||||
if (!InstRatio || InstRatio > 100)
|
||||
if (!InstRatio || InstRatio > 100) {
|
||||
FATAL("Bad value of the instrumentation ratio (must be between 1 and 100)");
|
||||
}
|
||||
|
||||
unsigned PrevLocSize = 0;
|
||||
unsigned PrevCallerSize = 0;
|
||||
@ -224,25 +227,28 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
/* Decide previous location vector size (must be a power of two) */
|
||||
VectorType *PrevLocTy = NULL;
|
||||
|
||||
if (Ngram && (Ngram < 2 || Ngram > NGRAM_SIZE_MAX))
|
||||
if (Ngram && (Ngram < 2 || Ngram > NGRAM_SIZE_MAX)) {
|
||||
FATAL(
|
||||
"Bad value of the Ngram size (must be between 2 and NGRAM_SIZE_MAX "
|
||||
"(%u))",
|
||||
NGRAM_SIZE_MAX);
|
||||
}
|
||||
|
||||
if (Ngram)
|
||||
if (Ngram) {
|
||||
PrevLocSize = Ngram - 1;
|
||||
else
|
||||
} else {
|
||||
PrevLocSize = 1;
|
||||
}
|
||||
|
||||
/* Decide K-Ctx vector size (must be a power of two) */
|
||||
VectorType *PrevCallerTy = NULL;
|
||||
|
||||
if (CtxK > CTX_MAX_K)
|
||||
if (CtxK > CTX_MAX_K) {
|
||||
FATAL(
|
||||
"Bad value of K for K-context sensitivity (must be between 1 and "
|
||||
"CTX_MAX_K (%u))",
|
||||
CTX_MAX_K);
|
||||
}
|
||||
|
||||
if (CtxK == 1) {
|
||||
CtxK = 0;
|
||||
@ -381,11 +387,13 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
|
||||
SmallVector<Constant *, 32> PrevLocShuffle = {UndefValue::get(Int32Ty)};
|
||||
|
||||
for (unsigned I = 0; I < PrevLocSize - 1; ++I)
|
||||
for (unsigned I = 0; I < PrevLocSize - 1; ++I) {
|
||||
PrevLocShuffle.push_back(ConstantInt::get(Int32Ty, I));
|
||||
}
|
||||
|
||||
for (int I = PrevLocSize; I < PrevLocVecSize; ++I)
|
||||
for (int I = PrevLocSize; I < PrevLocVecSize; ++I) {
|
||||
PrevLocShuffle.push_back(ConstantInt::get(Int32Ty, PrevLocSize));
|
||||
}
|
||||
|
||||
Constant *PrevLocShuffleMask = ConstantVector::get(PrevLocShuffle);
|
||||
|
||||
@ -393,11 +401,13 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
SmallVector<Constant *, 32> PrevCallerShuffle = {UndefValue::get(Int32Ty)};
|
||||
|
||||
if (CtxK) {
|
||||
for (unsigned I = 0; I < PrevCallerSize - 1; ++I)
|
||||
for (unsigned I = 0; I < PrevCallerSize - 1; ++I) {
|
||||
PrevCallerShuffle.push_back(ConstantInt::get(Int32Ty, I));
|
||||
}
|
||||
|
||||
for (int I = PrevCallerSize; I < PrevCallerVecSize; ++I)
|
||||
for (int I = PrevCallerSize; I < PrevCallerVecSize; ++I) {
|
||||
PrevCallerShuffle.push_back(ConstantInt::get(Int32Ty, PrevCallerSize));
|
||||
}
|
||||
|
||||
PrevCallerShuffleMask = ConstantVector::get(PrevCallerShuffle);
|
||||
}
|
||||
@ -424,7 +434,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
// if (!isInInstrumentList(&F)) { continue; }
|
||||
|
||||
if (F.size() < function_minimum_size) { continue; }
|
||||
if (DumpCFG) entry_bb[F.getName()] = &F.getEntryBlock();
|
||||
if (DumpCFG) { entry_bb[F.getName()] = &F.getEntryBlock(); }
|
||||
|
||||
std::list<Value *> todo;
|
||||
for (auto &BB : F) {
|
||||
@ -453,10 +463,9 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
// local variable on the stack
|
||||
LoadInst *PrevCtxLoad = IRB.CreateLoad(
|
||||
#if LLVM_VERSION_MAJOR >= 14
|
||||
IRB.getInt32Ty(),
|
||||
IRB.getInt32Ty(),
|
||||
#endif
|
||||
AFLContext
|
||||
);
|
||||
AFLContext);
|
||||
PrevCtxLoad->setMetadata(M.getMDKindID("nosanitize"),
|
||||
MDNode::get(C, None));
|
||||
PrevCtx = PrevCtxLoad;
|
||||
@ -465,7 +474,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
// does the function have calls? and is any of the calls larger than one
|
||||
// basic block?
|
||||
for (auto &BB_2 : F) {
|
||||
if (has_calls) break;
|
||||
if (has_calls) { break; }
|
||||
for (auto &IN : BB_2) {
|
||||
CallInst *callInst = nullptr;
|
||||
if ((callInst = dyn_cast<CallInst>(&IN))) {
|
||||
@ -500,7 +509,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
#endif
|
||||
{
|
||||
|
||||
if (Ctx) NewCtx = IRB.CreateXor(PrevCtx, NewCtx);
|
||||
if (Ctx) { NewCtx = IRB.CreateXor(PrevCtx, NewCtx); }
|
||||
StoreInst *StoreCtx = IRB.CreateStore(NewCtx, AFLContext);
|
||||
StoreCtx->setMetadata(M.getMDKindID("nosanitize"),
|
||||
MDNode::get(C, None));
|
||||
@ -508,13 +517,13 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
}
|
||||
}
|
||||
|
||||
if (RandBelow(100) >= InstRatio) continue;
|
||||
if (RandBelow(100) >= InstRatio) { continue; }
|
||||
|
||||
/* Make up cur_loc */
|
||||
|
||||
// cur_loc++;
|
||||
cur_loc = RandBelow(map_size);
|
||||
if (DumpCFG) bb_to_cur_loc[&BB] = cur_loc;
|
||||
if (DumpCFG) { bb_to_cur_loc[&BB] = cur_loc; }
|
||||
/* There is a problem with Ubuntu 18.04 and llvm 6.0 (see issue #63).
|
||||
The inline function successors() is not inlined and also not found at runtime
|
||||
:-( As I am unable to detect Ubuntu18.04 heree, the next best thing is to
|
||||
@ -531,7 +540,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
BasicBlock *Pred = *PI;
|
||||
|
||||
int count = 0;
|
||||
if (more_than_one == -1) more_than_one = 0;
|
||||
if (more_than_one == -1) { more_than_one = 0; }
|
||||
// fprintf(stderr, " %p=>", Pred);
|
||||
|
||||
for (succ_iterator SI = succ_begin(Pred), E = succ_end(Pred); SI != E;
|
||||
@ -540,11 +549,11 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
|
||||
// if (count > 0)
|
||||
// fprintf(stderr, "|");
|
||||
if (Succ != NULL) count++;
|
||||
if (Succ != NULL) { count++; }
|
||||
// fprintf(stderr, "%p", Succ);
|
||||
}
|
||||
|
||||
if (count > 1) more_than_one = 1;
|
||||
if (count > 1) { more_than_one = 1; }
|
||||
}
|
||||
|
||||
// fprintf(stderr, " == %d\n", more_than_one);
|
||||
@ -783,7 +792,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
cfg += formatv("->{0}\n", bb_to_cur_loc[*bb_successor]).str();
|
||||
}
|
||||
}
|
||||
if (Debug) errs() << "CFG: \n" << cfg;
|
||||
if (Debug) { errs() << "CFG: \n" << cfg; }
|
||||
if (cfg.size() > 0 && write(fd, cfg.c_str(), cfg.length()) <= 0)
|
||||
FATAL("Failed to dump CFG.\n");
|
||||
}
|
||||
|
@ -210,8 +210,9 @@ void dict2file(int fd, uint8_t *mem, uint32_t len) {
|
||||
|
||||
line[j] = 0;
|
||||
strcat(line, "\"\n");
|
||||
if (write(fd, line, strlen(line)) <= 0)
|
||||
if (write(fd, line, strlen(line)) <= 0) {
|
||||
FATAL("Could not write to the dictionary file");
|
||||
}
|
||||
fsync(fd);
|
||||
}
|
||||
|
||||
@ -248,7 +249,7 @@ bool AutoTokensPass::runOnModule(Module &M) {
|
||||
/* Instrument all the things! */
|
||||
|
||||
for (auto &F : M) {
|
||||
if (isIgnoreFunction(&F)) continue;
|
||||
if (isIgnoreFunction(&F)) { continue; }
|
||||
|
||||
/* Some implementation notes.
|
||||
*
|
||||
@ -294,8 +295,8 @@ bool AutoTokensPass::runOnModule(Module &M) {
|
||||
if (ilen && ilen->uge(0xffffffffffffffff) == false) {
|
||||
uint64_t val2 = 0, val = ilen->getZExtValue();
|
||||
uint32_t len = 0;
|
||||
if (val > 0x10000 && val < 0xffffffff) len = 4;
|
||||
if (val > 0x100000001 && val < 0xffffffffffffffff) len = 8;
|
||||
if (val > 0x10000 && val < 0xffffffff) { len = 4; }
|
||||
if (val > 0x100000001 && val < 0xffffffffffffffff) { len = 8; }
|
||||
|
||||
if (len) {
|
||||
auto c = cmpInst->getPredicate();
|
||||
@ -309,7 +310,7 @@ bool AutoTokensPass::runOnModule(Module &M) {
|
||||
// signed comparison and it is a negative constant
|
||||
if ((len == 4 && (val & 80000000)) ||
|
||||
(len == 8 && (val & 8000000000000000))) {
|
||||
if ((val & 0xffff) != 1) val2 = val - 1;
|
||||
if ((val & 0xffff) != 1) { val2 = val - 1; }
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -270,7 +270,7 @@ bool CmpLogRoutines::hookRtns(Module &M) {
|
||||
|
||||
/* iterate over all functions, bbs and instruction and add suitable calls */
|
||||
for (auto &F : M) {
|
||||
if (isIgnoreFunction(&F)) continue;
|
||||
if (isIgnoreFunction(&F)) { continue; }
|
||||
|
||||
for (auto &BB : F) {
|
||||
for (auto &IN : BB) {
|
||||
@ -278,8 +278,8 @@ bool CmpLogRoutines::hookRtns(Module &M) {
|
||||
|
||||
if ((callInst = dyn_cast<CallInst>(&IN))) {
|
||||
Function *Callee = callInst->getCalledFunction();
|
||||
if (!Callee) continue;
|
||||
if (callInst->getCallingConv() != llvm::CallingConv::C) continue;
|
||||
if (!Callee) { continue; }
|
||||
if (callInst->getCallingConv() != llvm::CallingConv::C) { continue; }
|
||||
|
||||
FunctionType *FT = Callee->getFunctionType();
|
||||
|
||||
@ -350,8 +350,9 @@ bool CmpLogRoutines::hookRtns(Module &M) {
|
||||
}
|
||||
|
||||
if (!calls.size() && !gccStdStd.size() && !gccStdC.size() &&
|
||||
!llvmStdStd.size() && !llvmStdC.size())
|
||||
!llvmStdStd.size() && !llvmStdC.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto &callInst : calls) {
|
||||
Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
|
||||
|
@ -20,18 +20,22 @@ typedef long double max_align_t;
|
||||
#endif
|
||||
|
||||
#ifdef USE_NEW_PM
|
||||
#include "llvm/Passes/PassPlugin.h"
|
||||
#include "llvm/Passes/PassBuilder.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
#include "llvm/Passes/PassPlugin.h"
|
||||
#include "llvm/Passes/PassBuilder.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
#else
|
||||
#include "llvm/IR/LegacyPassManager.h"
|
||||
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
|
||||
#include "llvm/IR/LegacyPassManager.h"
|
||||
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
|
||||
#endif
|
||||
|
||||
#define FATAL(...) do { fprintf(stderr, "FATAL: " __VA_ARGS__); exit(1); } while (0)
|
||||
#define FATAL(...) \
|
||||
do { \
|
||||
fprintf(stderr, "FATAL: " __VA_ARGS__); \
|
||||
exit(1); \
|
||||
} while (0)
|
||||
|
||||
static uint32_t RandBelow(uint32_t max) {
|
||||
return (uint32_t)rand() % (max +1);
|
||||
return (uint32_t)rand() % (max + 1);
|
||||
}
|
||||
|
||||
/* needed up to 3.9.0 */
|
||||
@ -39,7 +43,6 @@ static uint32_t RandBelow(uint32_t max) {
|
||||
(LLVM_VERSION_MINOR < 9 || \
|
||||
(LLVM_VERSION_MINOR == 9 && LLVM_VERSION_PATCH < 1))
|
||||
static uint64_t PowerOf2Ceil(unsigned in) {
|
||||
|
||||
uint64_t in64 = in - 1;
|
||||
in64 |= (in64 >> 1);
|
||||
in64 |= (in64 >> 2);
|
||||
@ -48,8 +51,7 @@ static uint64_t PowerOf2Ceil(unsigned in) {
|
||||
in64 |= (in64 >> 16);
|
||||
in64 |= (in64 >> 32);
|
||||
return in64 + 1;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LIBAFL_COMMON_LLVM_H
|
||||
#endif // LIBAFL_COMMON_LLVM_H
|
||||
|
@ -89,7 +89,7 @@ namespace {
|
||||
SECURITY_SENSITIVE_FUNCS(StringRef)
|
||||
|
||||
bool isSecuritySensitiveFunction(Function *F) {
|
||||
if (!F) return 0;
|
||||
if (!F) { return 0; }
|
||||
auto func_name = F->getName();
|
||||
for (auto name : securitySensitiveFunctions) {
|
||||
if (func_name.contains(name)) {
|
||||
@ -231,21 +231,23 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
BasicBlock::iterator IP = BB.getFirstInsertionPt();
|
||||
IRBuilder<> IRB(&(*IP));
|
||||
|
||||
if (RandBelow(100) >= InstRatio) continue;
|
||||
if (RandBelow(100) >= InstRatio) { continue; }
|
||||
|
||||
// Start with 1 to implicitly track edge coverage too
|
||||
uint32_t MemCnt = 1;
|
||||
for (auto &I : BB) {
|
||||
switch (granularity) {
|
||||
case BB_GRAN:
|
||||
if (I.mayReadFromMemory() || I.mayWriteToMemory()) ++MemCnt;
|
||||
case BB_GRAN: {
|
||||
if (I.mayReadFromMemory() || I.mayWriteToMemory()) { ++MemCnt; }
|
||||
break;
|
||||
case FUNC_GRAN:
|
||||
}
|
||||
case FUNC_GRAN: {
|
||||
if (auto *C = dyn_cast<CallInst>(&I)) {
|
||||
auto F = C->getCalledFunction();
|
||||
MemCnt += isSecuritySensitiveFunction(F);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Make up cur_loc */
|
||||
|
@ -1,36 +1,39 @@
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t* __afl_area_ptr;
|
||||
uint8_t* __afl_acc_memop_ptr;
|
||||
uint8_t *__afl_area_ptr;
|
||||
uint8_t *__afl_acc_memop_ptr;
|
||||
|
||||
void __libafl_targets_cmplog_instructions(uintptr_t k, uint8_t shape, uint64_t arg1, uint64_t arg2) {
|
||||
(void)k;
|
||||
(void)shape;
|
||||
(void)arg1;
|
||||
(void)arg2;
|
||||
void __libafl_targets_cmplog_instructions(uintptr_t k, uint8_t shape,
|
||||
uint64_t arg1, uint64_t arg2) {
|
||||
(void)k;
|
||||
(void)shape;
|
||||
(void)arg1;
|
||||
(void)arg2;
|
||||
}
|
||||
|
||||
void __cmplog_rtn_hook(uint8_t *ptr1, uint8_t *ptr2) {
|
||||
(void)ptr1;
|
||||
(void)ptr2;
|
||||
(void)ptr1;
|
||||
(void)ptr2;
|
||||
}
|
||||
|
||||
void __cmplog_rtn_gcc_stdstring_cstring(uint8_t *stdstring, uint8_t *cstring) {
|
||||
(void)stdstring;
|
||||
(void)cstring;
|
||||
(void)stdstring;
|
||||
(void)cstring;
|
||||
}
|
||||
|
||||
void __cmplog_rtn_gcc_stdstring_stdstring(uint8_t *stdstring1, uint8_t *stdstring2) {
|
||||
(void)stdstring1;
|
||||
(void)stdstring2;
|
||||
void __cmplog_rtn_gcc_stdstring_stdstring(uint8_t *stdstring1,
|
||||
uint8_t *stdstring2) {
|
||||
(void)stdstring1;
|
||||
(void)stdstring2;
|
||||
}
|
||||
|
||||
void __cmplog_rtn_llvm_stdstring_cstring(uint8_t *stdstring, uint8_t *cstring) {
|
||||
(void)stdstring;
|
||||
(void)cstring;
|
||||
(void)stdstring;
|
||||
(void)cstring;
|
||||
}
|
||||
|
||||
void __cmplog_rtn_llvm_stdstring_stdstring(uint8_t *stdstring1, uint8_t *stdstring2) {
|
||||
(void)stdstring1;
|
||||
(void)stdstring2;
|
||||
void __cmplog_rtn_llvm_stdstring_stdstring(uint8_t *stdstring1,
|
||||
uint8_t *stdstring2) {
|
||||
(void)stdstring1;
|
||||
(void)stdstring2;
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
#ifdef _MSC_VER
|
||||
__declspec( thread ) int i = 0;
|
||||
__declspec(thread) int i = 0;
|
||||
#else
|
||||
__thread int i = 0;
|
||||
#endif
|
||||
|
||||
void * tls_ptr() {
|
||||
return (void*)&i;
|
||||
void *tls_ptr() {
|
||||
return (void *)&i;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -34,18 +34,15 @@ long (*__lq_libc_atol)(const char *);
|
||||
long long (*__lq_libc_atoll)(const char *);
|
||||
|
||||
void __libqasan_init_hooks(void) {
|
||||
|
||||
__libqasan_init_malloc();
|
||||
|
||||
__lq_libc_fgets = ASSERT_DLSYM(fgets);
|
||||
__lq_libc_atoi = ASSERT_DLSYM(atoi);
|
||||
__lq_libc_atol = ASSERT_DLSYM(atol);
|
||||
__lq_libc_atoll = ASSERT_DLSYM(atoll);
|
||||
|
||||
}
|
||||
|
||||
ssize_t write(int fd, const void *buf, size_t count) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: write(%d, %p, %zu)\n", rtv, fd, buf, count);
|
||||
@ -54,11 +51,9 @@ ssize_t write(int fd, const void *buf, size_t count) {
|
||||
QASAN_DEBUG("\t\t = %zd\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
ssize_t read(int fd, void *buf, size_t count) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: read(%d, %p, %zu)\n", rtv, fd, buf, count);
|
||||
@ -67,12 +62,10 @@ ssize_t read(int fd, void *buf, size_t count) {
|
||||
QASAN_DEBUG("\t\t = %zd\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
size_t malloc_usable_size(const void *ptr) {
|
||||
|
||||
#else
|
||||
size_t malloc_usable_size(void *ptr) {
|
||||
|
||||
@ -85,11 +78,9 @@ size_t malloc_usable_size(void *ptr) {
|
||||
QASAN_DEBUG("\t\t = %zu\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
void *malloc(size_t size) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: malloc(%zu)\n", rtv, size);
|
||||
@ -97,11 +88,9 @@ void *malloc(size_t size) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
void *calloc(size_t nmemb, size_t size) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: calloc(%zu, %zu)\n", rtv, nmemb, size);
|
||||
@ -109,11 +98,9 @@ void *calloc(size_t nmemb, size_t size) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
void *realloc(void *ptr, size_t size) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: realloc(%p, %zu)\n", rtv, ptr, size);
|
||||
@ -121,11 +108,9 @@ void *realloc(void *ptr, size_t size) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
int posix_memalign(void **memptr, size_t alignment, size_t size) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: posix_memalign(%p, %zu, %zu)\n", rtv, memptr, alignment,
|
||||
@ -134,11 +119,9 @@ int posix_memalign(void **memptr, size_t alignment, size_t size) {
|
||||
QASAN_DEBUG("\t\t = %d [*memptr = %p]\n", r, *memptr);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
void *memalign(size_t alignment, size_t size) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: memalign(%zu, %zu)\n", rtv, alignment, size);
|
||||
@ -146,11 +129,9 @@ void *memalign(size_t alignment, size_t size) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
void *aligned_alloc(size_t alignment, size_t size) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: aligned_alloc(%zu, %zu)\n", rtv, alignment, size);
|
||||
@ -158,11 +139,9 @@ void *aligned_alloc(size_t alignment, size_t size) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
void *valloc(size_t size) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: valloc(%zu)\n", rtv, size);
|
||||
@ -170,11 +149,9 @@ void *valloc(size_t size) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
void *pvalloc(size_t size) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: pvalloc(%zu)\n", rtv, size);
|
||||
@ -184,20 +161,16 @@ void *pvalloc(size_t size) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
void free(void *ptr) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: free(%p)\n", rtv, ptr);
|
||||
__libqasan_free(ptr);
|
||||
|
||||
}
|
||||
|
||||
char *fgets(char *s, int size, FILE *stream) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: fgets(%p, %d, %p)\n", rtv, s, size, stream);
|
||||
@ -209,11 +182,9 @@ char *fgets(char *s, int size, FILE *stream) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
int memcmp(const void *s1, const void *s2, size_t n) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: memcmp(%p, %p, %zu)\n", rtv, s1, s2, n);
|
||||
@ -223,11 +194,9 @@ int memcmp(const void *s1, const void *s2, size_t n) {
|
||||
QASAN_DEBUG("\t\t = %d\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
void *memcpy(void *dest, const void *src, size_t n) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: memcpy(%p, %p, %zu)\n", rtv, dest, src, n);
|
||||
@ -237,11 +206,9 @@ void *memcpy(void *dest, const void *src, size_t n) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
void *mempcpy(void *dest, const void *src, size_t n) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: mempcpy(%p, %p, %zu)\n", rtv, dest, src, n);
|
||||
@ -251,11 +218,9 @@ void *mempcpy(void *dest, const void *src, size_t n) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
void *memmove(void *dest, const void *src, size_t n) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: memmove(%p, %p, %zu)\n", rtv, dest, src, n);
|
||||
@ -265,11 +230,9 @@ void *memmove(void *dest, const void *src, size_t n) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
void *memset(void *s, int c, size_t n) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: memset(%p, %d, %zu)\n", rtv, s, c, n);
|
||||
@ -278,27 +241,24 @@ void *memset(void *s, int c, size_t n) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
void *memchr(const void *s, int c, size_t n) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: memchr(%p, %d, %zu)\n", rtv, s, c, n);
|
||||
void *r = __libqasan_memchr(s, c, n);
|
||||
if (r == NULL)
|
||||
if (r == NULL) {
|
||||
QASAN_LOAD(s, n);
|
||||
else
|
||||
} else {
|
||||
QASAN_LOAD(s, r - s);
|
||||
}
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
void *memrchr(const void *s, int c, size_t n) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: memrchr(%p, %d, %zu)\n", rtv, s, c, n);
|
||||
@ -307,12 +267,10 @@ void *memrchr(const void *s, int c, size_t n) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
void *memmem(const void *haystack, size_t haystacklen, const void *needle,
|
||||
size_t needlelen) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: memmem(%p, %zu, %p, %zu)\n", rtv, haystack, haystacklen,
|
||||
@ -323,34 +281,28 @@ void *memmem(const void *haystack, size_t haystacklen, const void *needle,
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
#ifndef __BIONIC__
|
||||
void bzero(void *s, size_t n) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: bzero(%p, %zu)\n", rtv, s, n);
|
||||
QASAN_STORE(s, n);
|
||||
__libqasan_memset(s, 0, n);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void explicit_bzero(void *s, size_t n) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: bzero(%p, %zu)\n", rtv, s, n);
|
||||
QASAN_STORE(s, n);
|
||||
__libqasan_memset(s, 0, n);
|
||||
|
||||
}
|
||||
|
||||
int bcmp(const void *s1, const void *s2, size_t n) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: bcmp(%p, %p, %zu)\n", rtv, s1, s2, n);
|
||||
@ -360,11 +312,9 @@ int bcmp(const void *s1, const void *s2, size_t n) {
|
||||
QASAN_DEBUG("\t\t = %d\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
char *strchr(const char *s, int c) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: strchr(%p, %d)\n", rtv, s, c);
|
||||
@ -374,11 +324,9 @@ char *strchr(const char *s, int c) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
char *strrchr(const char *s, int c) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: strrchr(%p, %d)\n", rtv, s, c);
|
||||
@ -388,11 +336,9 @@ char *strrchr(const char *s, int c) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
int strcasecmp(const char *s1, const char *s2) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: strcasecmp(%p, %p)\n", rtv, s1, s2);
|
||||
@ -404,11 +350,9 @@ int strcasecmp(const char *s1, const char *s2) {
|
||||
QASAN_DEBUG("\t\t = %d\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
int strncasecmp(const char *s1, const char *s2, size_t n) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: strncasecmp(%p, %p, %zu)\n", rtv, s1, s2, n);
|
||||
@ -420,11 +364,9 @@ int strncasecmp(const char *s1, const char *s2, size_t n) {
|
||||
QASAN_DEBUG("\t\t = %d\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
char *strcat(char *dest, const char *src) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: strcat(%p, %p)\n", rtv, dest, src);
|
||||
@ -438,11 +380,9 @@ char *strcat(char *dest, const char *src) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
int strcmp(const char *s1, const char *s2) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: strcmp(%p, %p)\n", rtv, s1, s2);
|
||||
@ -454,11 +394,9 @@ int strcmp(const char *s1, const char *s2) {
|
||||
QASAN_DEBUG("\t\t = %d\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
int strncmp(const char *s1, const char *s2, size_t n) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: strncmp(%p, %p, %zu)\n", rtv, s1, s2, n);
|
||||
@ -470,11 +408,9 @@ int strncmp(const char *s1, const char *s2, size_t n) {
|
||||
QASAN_DEBUG("\t\t = %d\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
char *strcpy(char *dest, const char *src) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: strcpy(%p, %p)\n", rtv, dest, src);
|
||||
@ -485,11 +421,9 @@ char *strcpy(char *dest, const char *src) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
char *strncpy(char *dest, const char *src, size_t n) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: strncpy(%p, %p, %zu)\n", rtv, dest, src, n);
|
||||
@ -497,25 +431,20 @@ char *strncpy(char *dest, const char *src, size_t n) {
|
||||
QASAN_STORE(dest, n);
|
||||
void *r;
|
||||
if (l < n) {
|
||||
|
||||
QASAN_LOAD(src, l + 1);
|
||||
r = __libqasan_memcpy(dest, src, l + 1);
|
||||
|
||||
} else {
|
||||
|
||||
QASAN_LOAD(src, n);
|
||||
r = __libqasan_memcpy(dest, src, n);
|
||||
|
||||
}
|
||||
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
char *stpcpy(char *dest, const char *src) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: stpcpy(%p, %p)\n", rtv, dest, src);
|
||||
@ -526,11 +455,9 @@ char *stpcpy(char *dest, const char *src) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
char *strdup(const char *s) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: strdup(%p)\n", rtv, s);
|
||||
@ -541,11 +468,9 @@ char *strdup(const char *s) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
size_t strlen(const char *s) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: strlen(%p)\n", rtv, s);
|
||||
@ -554,11 +479,9 @@ size_t strlen(const char *s) {
|
||||
QASAN_DEBUG("\t\t = %zu\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
size_t strnlen(const char *s, size_t n) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: strnlen(%p, %zu)\n", rtv, s, n);
|
||||
@ -567,11 +490,9 @@ size_t strnlen(const char *s, size_t n) {
|
||||
QASAN_DEBUG("\t\t = %zu\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
char *strstr(const char *haystack, const char *needle) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: strstr(%p, %p)\n", rtv, haystack, needle);
|
||||
@ -583,11 +504,9 @@ char *strstr(const char *haystack, const char *needle) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
char *strcasestr(const char *haystack, const char *needle) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: strcasestr(%p, %p)\n", rtv, haystack, needle);
|
||||
@ -599,11 +518,9 @@ char *strcasestr(const char *haystack, const char *needle) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
int atoi(const char *nptr) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: atoi(%p)\n", rtv, nptr);
|
||||
@ -613,11 +530,9 @@ int atoi(const char *nptr) {
|
||||
QASAN_DEBUG("\t\t = %d\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
long atol(const char *nptr) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: atol(%p)\n", rtv, nptr);
|
||||
@ -627,11 +542,9 @@ long atol(const char *nptr) {
|
||||
QASAN_DEBUG("\t\t = %ld\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
long long atoll(const char *nptr) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: atoll(%p)\n", rtv, nptr);
|
||||
@ -641,11 +554,9 @@ long long atoll(const char *nptr) {
|
||||
QASAN_DEBUG("\t\t = %lld\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
size_t wcslen(const wchar_t *s) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: wcslen(%p)\n", rtv, s);
|
||||
@ -654,11 +565,9 @@ size_t wcslen(const wchar_t *s) {
|
||||
QASAN_DEBUG("\t\t = %zu\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
wchar_t *wcscpy(wchar_t *dest, const wchar_t *src) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: wcscpy(%p, %p)\n", rtv, dest, src);
|
||||
@ -669,11 +578,9 @@ wchar_t *wcscpy(wchar_t *dest, const wchar_t *src) {
|
||||
QASAN_DEBUG("\t\t = %p\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
int wcscmp(const wchar_t *s1, const wchar_t *s2) {
|
||||
|
||||
void *rtv = __builtin_return_address(0);
|
||||
|
||||
QASAN_DEBUG("%14p: wcscmp(%p, %p)\n", rtv, s1, s2);
|
||||
@ -685,6 +592,4 @@ int wcscmp(const wchar_t *s1, const wchar_t *s2) {
|
||||
QASAN_DEBUG("\t\t = %d\n", r);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,6 @@ int __qasan_debug;
|
||||
int __qasan_log;
|
||||
|
||||
void __libqasan_print_maps(void) {
|
||||
|
||||
int fd = open("/proc/self/maps", O_RDONLY);
|
||||
char buf[4096] = {0};
|
||||
|
||||
@ -44,33 +43,30 @@ void __libqasan_print_maps(void) {
|
||||
int i;
|
||||
char *line = NULL;
|
||||
for (i = 0; i < len; i++) {
|
||||
|
||||
if (!line) line = &buf[i];
|
||||
if (buf[i] == '\n') {
|
||||
|
||||
buf[i] = 0;
|
||||
QASAN_LOG("%s\n", line);
|
||||
line = NULL;
|
||||
|
||||
}
|
||||
|
||||
if (!line) line = { &buf[i];
|
||||
}
|
||||
if (buf[i] == '\n') {
|
||||
buf[i] = 0;
|
||||
QASAN_LOG("%s\n", line);
|
||||
line = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (line) QASAN_LOG("%s\n", line);
|
||||
QASAN_LOG("\n");
|
||||
|
||||
if (line) { QASAN_LOG("%s\n", line); }
|
||||
QASAN_LOG("\n");
|
||||
}
|
||||
|
||||
int __libqasan_is_initialized = 0;
|
||||
|
||||
__attribute__((constructor)) void __libqasan_init() {
|
||||
|
||||
if (__libqasan_is_initialized) return;
|
||||
if (__libqasan_is_initialized) { return; }
|
||||
__libqasan_is_initialized = 1;
|
||||
|
||||
__libqasan_init_hooks();
|
||||
|
||||
if (getenv("AFL_INST_LIBS") || getenv("QASAN_HOTPACH")) __libqasan_hotpatch();
|
||||
if (getenv("AFL_INST_LIBS") || getenv("QASAN_HOTPACH")) {
|
||||
__libqasan_hotpatch();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
__qasan_debug = getenv("QASAN_DEBUG") != NULL;
|
||||
@ -82,19 +78,15 @@ __attribute__((constructor)) void __libqasan_init() {
|
||||
"Copyright (C) 2019-2021 Andrea Fioraldi <andreafioraldi@gmail.com>\n");
|
||||
QASAN_LOG("\n");
|
||||
|
||||
if (__qasan_log) __libqasan_print_maps();
|
||||
|
||||
if (__qasan_log) { __libqasan_print_maps(); }
|
||||
}
|
||||
|
||||
int __libc_start_main(int (*main)(int, char **, char **), int argc, char **argv,
|
||||
int (*init)(int, char **, char **), void (*fini)(void),
|
||||
void (*rtld_fini)(void), void *stack_end) {
|
||||
|
||||
typeof(&__libc_start_main) orig = dlsym(RTLD_NEXT, "__libc_start_main");
|
||||
|
||||
__libqasan_init();
|
||||
|
||||
return orig(main, argc, argv, init, fini, rtld_fini, stack_end);
|
||||
|
||||
}
|
||||
|
||||
|
@ -43,12 +43,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#define QASAN_LOG(msg...) \
|
||||
do { \
|
||||
\
|
||||
if (__qasan_log) { \
|
||||
\
|
||||
fprintf(stderr, "==%d== ", getpid()); \
|
||||
fprintf(stderr, msg); \
|
||||
\
|
||||
} \
|
||||
\
|
||||
} while (0)
|
||||
@ -56,12 +53,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifdef DEBUG
|
||||
#define QASAN_DEBUG(msg...) \
|
||||
do { \
|
||||
\
|
||||
if (__qasan_debug) { \
|
||||
\
|
||||
fprintf(stderr, "==%d== ", getpid()); \
|
||||
fprintf(stderr, msg); \
|
||||
\
|
||||
} \
|
||||
\
|
||||
} while (0)
|
||||
@ -69,23 +63,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#else
|
||||
#define QASAN_DEBUG(msg...) \
|
||||
do { \
|
||||
\
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define ASSERT_DLSYM(name) \
|
||||
({ \
|
||||
\
|
||||
void *a = (void *)dlsym(RTLD_NEXT, #name); \
|
||||
if (!a) { \
|
||||
\
|
||||
fprintf(stderr, \
|
||||
"FATAL ERROR: failed dlsym of " #name " in libqasan!\n"); \
|
||||
abort(); \
|
||||
\
|
||||
} \
|
||||
a; \
|
||||
\
|
||||
})
|
||||
|
||||
extern int __qasan_debug;
|
||||
@ -97,19 +86,19 @@ void __libqasan_init_malloc(void);
|
||||
void __libqasan_hotpatch(void);
|
||||
|
||||
size_t __libqasan_malloc_usable_size(void *ptr);
|
||||
void * __libqasan_malloc(size_t size);
|
||||
void *__libqasan_malloc(size_t size);
|
||||
void __libqasan_free(void *ptr);
|
||||
void * __libqasan_calloc(size_t nmemb, size_t size);
|
||||
void * __libqasan_realloc(void *ptr, size_t size);
|
||||
void *__libqasan_calloc(size_t nmemb, size_t size);
|
||||
void *__libqasan_realloc(void *ptr, size_t size);
|
||||
int __libqasan_posix_memalign(void **ptr, size_t align, size_t len);
|
||||
void * __libqasan_memalign(size_t align, size_t len);
|
||||
void * __libqasan_aligned_alloc(size_t align, size_t len);
|
||||
void *__libqasan_memalign(size_t align, size_t len);
|
||||
void *__libqasan_aligned_alloc(size_t align, size_t len);
|
||||
|
||||
void * __libqasan_memcpy(void *dest, const void *src, size_t n);
|
||||
void * __libqasan_memmove(void *dest, const void *src, size_t n);
|
||||
void * __libqasan_memset(void *s, int c, size_t n);
|
||||
void * __libqasan_memchr(const void *s, int c, size_t n);
|
||||
void * __libqasan_memrchr(const void *s, int c, size_t n);
|
||||
void *__libqasan_memcpy(void *dest, const void *src, size_t n);
|
||||
void *__libqasan_memmove(void *dest, const void *src, size_t n);
|
||||
void *__libqasan_memset(void *s, int c, size_t n);
|
||||
void *__libqasan_memchr(const void *s, int c, size_t n);
|
||||
void *__libqasan_memrchr(const void *s, int c, size_t n);
|
||||
size_t __libqasan_strlen(const char *s);
|
||||
size_t __libqasan_strnlen(const char *s, size_t len);
|
||||
int __libqasan_strcmp(const char *str1, const char *str2);
|
||||
@ -118,15 +107,14 @@ int __libqasan_strcasecmp(const char *str1, const char *str2);
|
||||
int __libqasan_strncasecmp(const char *str1, const char *str2, size_t len);
|
||||
int __libqasan_memcmp(const void *mem1, const void *mem2, size_t len);
|
||||
int __libqasan_bcmp(const void *mem1, const void *mem2, size_t len);
|
||||
char * __libqasan_strstr(const char *haystack, const char *needle);
|
||||
char * __libqasan_strcasestr(const char *haystack, const char *needle);
|
||||
void * __libqasan_memmem(const void *haystack, size_t haystack_len,
|
||||
char *__libqasan_strstr(const char *haystack, const char *needle);
|
||||
char *__libqasan_strcasestr(const char *haystack, const char *needle);
|
||||
void *__libqasan_memmem(const void *haystack, size_t haystack_len,
|
||||
const void *needle, size_t needle_len);
|
||||
char * __libqasan_strchr(const char *s, int c);
|
||||
char * __libqasan_strrchr(const char *s, int c);
|
||||
char *__libqasan_strchr(const char *s, int c);
|
||||
char *__libqasan_strrchr(const char *s, int c);
|
||||
size_t __libqasan_wcslen(const wchar_t *s);
|
||||
wchar_t *__libqasan_wcscpy(wchar_t *d, const wchar_t *s);
|
||||
int __libqasan_wcscmp(const wchar_t *s1, const wchar_t *s2);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -38,7 +38,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
(defined(__FreeBSD__) && __FreeBSD_version < 1200000)
|
||||
// use this hack if not C11
|
||||
typedef struct {
|
||||
|
||||
long long __ll;
|
||||
long double __ld;
|
||||
|
||||
@ -49,21 +48,17 @@ typedef struct {
|
||||
#define ALLOC_ALIGN_SIZE (_Alignof(max_align_t))
|
||||
|
||||
struct chunk_begin {
|
||||
|
||||
size_t requested_size;
|
||||
void * aligned_orig; // NULL if not aligned
|
||||
void *aligned_orig; // NULL if not aligned
|
||||
struct chunk_begin *next;
|
||||
struct chunk_begin *prev;
|
||||
char redzone[REDZONE_SIZE];
|
||||
|
||||
};
|
||||
|
||||
struct chunk_struct {
|
||||
|
||||
struct chunk_begin begin;
|
||||
char redzone[REDZONE_SIZE];
|
||||
size_t prev_size_padding;
|
||||
|
||||
};
|
||||
|
||||
#ifdef __GLIBC__
|
||||
@ -80,7 +75,7 @@ static unsigned char __tmp_alloc_zone[TMP_ZONE_SIZE];
|
||||
#else
|
||||
|
||||
// From dlmalloc.c
|
||||
void * dlmalloc(size_t);
|
||||
void *dlmalloc(size_t);
|
||||
void dlfree(void *);
|
||||
#define backend_malloc dlmalloc
|
||||
#define backend_free dlfree
|
||||
@ -107,13 +102,11 @@ static pthread_spinlock_t quarantine_lock;
|
||||
|
||||
// need qasan disabled
|
||||
static int quarantine_push(struct chunk_begin *ck) {
|
||||
|
||||
if (ck->requested_size >= QUARANTINE_MAX_BYTES) return 0;
|
||||
|
||||
if (LOCK_TRY(&quarantine_lock)) return 0;
|
||||
|
||||
while (ck->requested_size + quarantine_bytes >= QUARANTINE_MAX_BYTES) {
|
||||
|
||||
struct chunk_begin *tmp = quarantine_end;
|
||||
quarantine_end = tmp->prev;
|
||||
|
||||
@ -123,7 +116,6 @@ static int quarantine_push(struct chunk_begin *ck) {
|
||||
backend_free(tmp->aligned_orig);
|
||||
else
|
||||
backend_free(tmp);
|
||||
|
||||
}
|
||||
|
||||
ck->next = quarantine_top;
|
||||
@ -133,11 +125,9 @@ static int quarantine_push(struct chunk_begin *ck) {
|
||||
LOCK_UNLOCK(&quarantine_lock);
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
void __libqasan_init_malloc(void) {
|
||||
|
||||
if (__libqasan_malloc_initialized) return;
|
||||
|
||||
#ifdef __GLIBC__
|
||||
@ -151,11 +141,9 @@ void __libqasan_init_malloc(void) {
|
||||
QASAN_LOG("\n");
|
||||
QASAN_LOG("Allocator initialization done.\n");
|
||||
QASAN_LOG("\n");
|
||||
|
||||
}
|
||||
|
||||
size_t __libqasan_malloc_usable_size(void *ptr) {
|
||||
|
||||
char *p = ptr;
|
||||
p -= sizeof(struct chunk_begin);
|
||||
|
||||
@ -163,13 +151,10 @@ size_t __libqasan_malloc_usable_size(void *ptr) {
|
||||
// to verify that ptr is a valid malloc region before we dereference it)
|
||||
QASAN_LOAD(p, sizeof(struct chunk_begin) - REDZONE_SIZE);
|
||||
return ((struct chunk_begin *)p)->requested_size;
|
||||
|
||||
}
|
||||
|
||||
void *__libqasan_malloc(size_t size) {
|
||||
|
||||
if (!__libqasan_malloc_initialized) {
|
||||
|
||||
__libqasan_init_malloc();
|
||||
|
||||
#ifdef __GLIBC__
|
||||
@ -183,7 +168,6 @@ void *__libqasan_malloc(size_t size) {
|
||||
|
||||
return r;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
int state = QASAN_SWAP(QASAN_DISABLED); // disable qasan for this thread
|
||||
@ -212,11 +196,9 @@ void *__libqasan_malloc(size_t size) {
|
||||
__builtin_memset(&p[1], 0xff, size);
|
||||
|
||||
return &p[1];
|
||||
|
||||
}
|
||||
|
||||
void __libqasan_free(void *ptr) {
|
||||
|
||||
if (!ptr) return;
|
||||
|
||||
#ifdef __GLIBC__
|
||||
@ -237,12 +219,10 @@ void __libqasan_free(void *ptr) {
|
||||
int state = QASAN_SWAP(QASAN_DISABLED); // disable qasan for this thread
|
||||
|
||||
if (!quarantine_push(p)) {
|
||||
|
||||
if (p->aligned_orig)
|
||||
backend_free(p->aligned_orig);
|
||||
else
|
||||
backend_free(p);
|
||||
|
||||
}
|
||||
|
||||
QASAN_SWAP(state);
|
||||
@ -252,20 +232,16 @@ void __libqasan_free(void *ptr) {
|
||||
|
||||
QASAN_POISON(ptr, n, ASAN_HEAP_FREED);
|
||||
QASAN_DEALLOC(ptr);
|
||||
|
||||
}
|
||||
|
||||
void *__libqasan_calloc(size_t nmemb, size_t size) {
|
||||
|
||||
size *= nmemb;
|
||||
|
||||
#ifdef __GLIBC__
|
||||
if (!__libqasan_malloc_initialized) {
|
||||
|
||||
void *r = &__tmp_alloc_zone[__tmp_alloc_zone_idx];
|
||||
__tmp_alloc_zone_idx += size;
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -276,11 +252,9 @@ void *__libqasan_calloc(size_t nmemb, size_t size) {
|
||||
__builtin_memset(p, 0, size);
|
||||
|
||||
return p;
|
||||
|
||||
}
|
||||
|
||||
void *__libqasan_realloc(void *ptr, size_t size) {
|
||||
|
||||
char *p = __libqasan_malloc(size);
|
||||
if (!p) return NULL;
|
||||
|
||||
@ -293,17 +267,13 @@ void *__libqasan_realloc(void *ptr, size_t size) {
|
||||
|
||||
__libqasan_free(ptr);
|
||||
return p;
|
||||
|
||||
}
|
||||
|
||||
int __libqasan_posix_memalign(void **ptr, size_t align, size_t len) {
|
||||
|
||||
if ((align % 2) || (align % sizeof(void *))) return EINVAL;
|
||||
if (len == 0) {
|
||||
|
||||
*ptr = NULL;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
size_t rem = len % align;
|
||||
@ -343,21 +313,17 @@ int __libqasan_posix_memalign(void **ptr, size_t align, size_t len) {
|
||||
*ptr = data;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void *__libqasan_memalign(size_t align, size_t len) {
|
||||
|
||||
void *ret = NULL;
|
||||
|
||||
__libqasan_posix_memalign(&ret, align, len);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
void *__libqasan_aligned_alloc(size_t align, size_t len) {
|
||||
|
||||
void *ret = NULL;
|
||||
|
||||
if ((len % align)) return NULL;
|
||||
@ -365,6 +331,4 @@ void *__libqasan_aligned_alloc(size_t align, size_t len) {
|
||||
__libqasan_posix_memalign(&ret, align, len);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
@ -71,4 +71,3 @@
|
||||
EVAL(MAP_LIST1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -29,7 +29,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifdef __x86_64__
|
||||
|
||||
uint8_t *__libqasan_patch_jump(uint8_t *addr, uint8_t *dest) {
|
||||
|
||||
// mov rax, dest
|
||||
addr[0] = 0x48;
|
||||
addr[1] = 0xb8;
|
||||
@ -40,13 +39,11 @@ uint8_t *__libqasan_patch_jump(uint8_t *addr, uint8_t *dest) {
|
||||
addr[11] = 0xe0;
|
||||
|
||||
return &addr[12];
|
||||
|
||||
}
|
||||
|
||||
#elif __i386__
|
||||
|
||||
uint8_t *__libqasan_patch_jump(uint8_t *addr, uint8_t *dest) {
|
||||
|
||||
// mov eax, dest
|
||||
addr[0] = 0xb8;
|
||||
*(uint8_t **)&addr[1] = dest;
|
||||
@ -56,7 +53,6 @@ uint8_t *__libqasan_patch_jump(uint8_t *addr, uint8_t *dest) {
|
||||
addr[6] = 0xe0;
|
||||
|
||||
return &addr[7];
|
||||
|
||||
}
|
||||
|
||||
#elif __arm__
|
||||
@ -65,7 +61,6 @@ uint8_t *__libqasan_patch_jump(uint8_t *addr, uint8_t *dest) {
|
||||
// so let's use it in our stub
|
||||
|
||||
uint8_t *__libqasan_patch_jump(uint8_t *addr, uint8_t *dest) {
|
||||
|
||||
// ldr r12, OFF
|
||||
addr[0] = 0x0;
|
||||
addr[1] = 0xc0;
|
||||
@ -82,7 +77,6 @@ uint8_t *__libqasan_patch_jump(uint8_t *addr, uint8_t *dest) {
|
||||
*(uint32_t *)&addr[8] = (uint32_t)dest;
|
||||
|
||||
return &addr[12];
|
||||
|
||||
}
|
||||
|
||||
#elif __aarch64__
|
||||
@ -91,7 +85,6 @@ uint8_t *__libqasan_patch_jump(uint8_t *addr, uint8_t *dest) {
|
||||
// so let's use it in our stub
|
||||
|
||||
uint8_t *__libqasan_patch_jump(uint8_t *addr, uint8_t *dest) {
|
||||
|
||||
// ldr x16, OFF
|
||||
addr[0] = 0x50;
|
||||
addr[1] = 0x0;
|
||||
@ -108,7 +101,6 @@ uint8_t *__libqasan_patch_jump(uint8_t *addr, uint8_t *dest) {
|
||||
*(uint64_t *)&addr[8] = (uint64_t)dest;
|
||||
|
||||
return &addr[16];
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
@ -120,7 +112,6 @@ uint8_t *__libqasan_patch_jump(uint8_t *addr, uint8_t *dest) {
|
||||
#ifdef CANNOT_HOTPATCH
|
||||
|
||||
void __libqasan_hotpatch(void) {
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
@ -129,17 +120,15 @@ static void *libc_start, *libc_end;
|
||||
int libc_perms;
|
||||
|
||||
static void find_libc(void) {
|
||||
|
||||
FILE * fp;
|
||||
char * line = NULL;
|
||||
FILE *fp;
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
ssize_t read;
|
||||
|
||||
fp = fopen("/proc/self/maps", "r");
|
||||
if (fp == NULL) return;
|
||||
if (fp == NULL) { return; }
|
||||
|
||||
while ((read = getline(&line, &len, fp)) != -1) {
|
||||
|
||||
int fields, dev_maj, dev_min, inode;
|
||||
uint64_t min, max, offset;
|
||||
char flag_r, flag_w, flag_x, flag_p;
|
||||
@ -151,27 +140,23 @@ static void find_libc(void) {
|
||||
&min, &max, &flag_r, &flag_w, &flag_x, &flag_p, &offset,
|
||||
&dev_maj, &dev_min, &inode, path);
|
||||
|
||||
if ((fields < 10) || (fields > 11)) continue;
|
||||
if ((fields < 10) || (fields > 11)) { continue; }
|
||||
|
||||
if (flag_x == 'x' && (__libqasan_strstr(path, "/libc.so") ||
|
||||
__libqasan_strstr(path, "/libc-"))) {
|
||||
|
||||
libc_start = (void *)min;
|
||||
libc_end = (void *)max;
|
||||
|
||||
libc_perms = PROT_EXEC;
|
||||
if (flag_w == 'w') libc_perms |= PROT_WRITE;
|
||||
if (flag_r == 'r') libc_perms |= PROT_READ;
|
||||
if (flag_w == 'w') { libc_perms |= PROT_WRITE; }
|
||||
if (flag_r == 'r') { libc_perms |= PROT_READ; }
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
free(line);
|
||||
fclose(fp);
|
||||
|
||||
}
|
||||
|
||||
/* Why this shit? https://twitter.com/andreafioraldi/status/1227635146452541441
|
||||
@ -181,28 +166,29 @@ static void find_libc(void) {
|
||||
*/
|
||||
|
||||
void __libqasan_hotpatch(void) {
|
||||
|
||||
find_libc();
|
||||
|
||||
if (!libc_start) return;
|
||||
if (!libc_start) { return; }
|
||||
|
||||
if (mprotect(libc_start, libc_end - libc_start,
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC) < 0)
|
||||
PROT_READ | PROT_WRITE | PROT_EXEC) < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
void *libc = dlopen("libc.so.6", RTLD_LAZY);
|
||||
|
||||
#define HOTPATCH(fn) \
|
||||
uint8_t *p_##fn = (uint8_t *)dlsym(libc, #fn); \
|
||||
if (p_##fn) __libqasan_patch_jump(p_##fn, (uint8_t *)&(fn));
|
||||
if (p_##fn) { __libqasan_patch_jump(p_##fn, (uint8_t *)&(fn)); }
|
||||
|
||||
HOTPATCH(memcmp)
|
||||
HOTPATCH(memmove)
|
||||
|
||||
uint8_t *p_memcpy = (uint8_t *)dlsym(libc, "memcpy");
|
||||
// fuck you libc
|
||||
if (p_memcpy && p_memmove != p_memcpy)
|
||||
if (p_memcpy && p_memmove != p_memcpy) {
|
||||
__libqasan_patch_jump(p_memcpy, (uint8_t *)&memcpy);
|
||||
}
|
||||
|
||||
HOTPATCH(memchr)
|
||||
HOTPATCH(memrchr)
|
||||
@ -236,8 +222,6 @@ void __libqasan_hotpatch(void) {
|
||||
#undef HOTPATCH
|
||||
|
||||
mprotect(libc_start, libc_end - libc_start, libc_perms);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -76,8 +76,7 @@ enum {
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#define QASAN_CALL0(action) \
|
||||
syscall(QASAN_FAKESYS_NR, action, NULL, NULL, NULL)
|
||||
#define QASAN_CALL0(action) syscall(QASAN_FAKESYS_NR, action, NULL, NULL, NULL)
|
||||
#define QASAN_CALL1(action, arg1) \
|
||||
syscall(QASAN_FAKESYS_NR, action, arg1, NULL, NULL)
|
||||
#define QASAN_CALL2(action, arg1, arg2) \
|
||||
@ -85,26 +84,19 @@ enum {
|
||||
#define QASAN_CALL3(action, arg1, arg2, arg3) \
|
||||
syscall(QASAN_FAKESYS_NR, action, arg1, arg2, arg3)
|
||||
|
||||
#define QASAN_LOAD(ptr, len) \
|
||||
QASAN_CALL2(QASAN_ACTION_CHECK_LOAD, ptr, len)
|
||||
#define QASAN_STORE(ptr, len) \
|
||||
QASAN_CALL2(QASAN_ACTION_CHECK_STORE, ptr, len)
|
||||
#define QASAN_LOAD(ptr, len) QASAN_CALL2(QASAN_ACTION_CHECK_LOAD, ptr, len)
|
||||
#define QASAN_STORE(ptr, len) QASAN_CALL2(QASAN_ACTION_CHECK_STORE, ptr, len)
|
||||
|
||||
#define QASAN_POISON(ptr, len, poison_byte) \
|
||||
QASAN_CALL3(QASAN_ACTION_POISON, ptr, len, poison_byte)
|
||||
#define QASAN_USER_POISON(ptr, len) \
|
||||
QASAN_CALL3(QASAN_ACTION_POISON, ptr, len, ASAN_USER)
|
||||
#define QASAN_UNPOISON(ptr, len) \
|
||||
QASAN_CALL2(QASAN_ACTION_UNPOISON, ptr, len)
|
||||
#define QASAN_IS_POISON(ptr, len) \
|
||||
QASAN_CALL2(QASAN_ACTION_IS_POISON, ptr, len)
|
||||
#define QASAN_UNPOISON(ptr, len) QASAN_CALL2(QASAN_ACTION_UNPOISON, ptr, len)
|
||||
#define QASAN_IS_POISON(ptr, len) QASAN_CALL2(QASAN_ACTION_IS_POISON, ptr, len)
|
||||
|
||||
#define QASAN_ALLOC(start, end) \
|
||||
QASAN_CALL2(QASAN_ACTION_ALLOC, start, end)
|
||||
#define QASAN_DEALLOC(ptr) \
|
||||
QASAN_CALL1(QASAN_ACTION_DEALLOC, ptr)
|
||||
#define QASAN_ALLOC(start, end) QASAN_CALL2(QASAN_ACTION_ALLOC, start, end)
|
||||
#define QASAN_DEALLOC(ptr) QASAN_CALL1(QASAN_ACTION_DEALLOC, ptr)
|
||||
|
||||
#define QASAN_SWAP(state) \
|
||||
QASAN_CALL1(QASAN_ACTION_SWAP_STATE, state)
|
||||
#define QASAN_SWAP(state) QASAN_CALL1(QASAN_ACTION_SWAP_STATE, state)
|
||||
|
||||
#endif
|
||||
|
@ -27,33 +27,30 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <ctype.h>
|
||||
|
||||
void *__libqasan_memcpy(void *dest, const void *src, size_t n) {
|
||||
|
||||
unsigned char * d = dest;
|
||||
unsigned char *d = dest;
|
||||
const unsigned char *s = src;
|
||||
|
||||
if (!n) return dest;
|
||||
if (!n) { return dest; }
|
||||
|
||||
while (n--) {
|
||||
|
||||
*d = *s;
|
||||
++d;
|
||||
++s;
|
||||
|
||||
}
|
||||
|
||||
return dest;
|
||||
|
||||
}
|
||||
|
||||
void *__libqasan_memmove(void *dest, const void *src, size_t n) {
|
||||
|
||||
unsigned char * d = dest;
|
||||
unsigned char *d = dest;
|
||||
const unsigned char *s = src;
|
||||
|
||||
if (!n) return dest;
|
||||
if (!n) { return dest; }
|
||||
|
||||
if (!((d + n) >= s && d <= (s + n))) // do not overlap
|
||||
{
|
||||
return __libqasan_memcpy(dest, src, n);
|
||||
}
|
||||
|
||||
d = __libqasan_malloc(n);
|
||||
__libqasan_memcpy(d, src, n);
|
||||
@ -62,199 +59,165 @@ void *__libqasan_memmove(void *dest, const void *src, size_t n) {
|
||||
__libqasan_free(d);
|
||||
|
||||
return dest;
|
||||
|
||||
}
|
||||
|
||||
void *__libqasan_memset(void *s, int c, size_t n) {
|
||||
|
||||
unsigned char *b = s;
|
||||
while (n--)
|
||||
while (n--) {
|
||||
*(b++) = (unsigned char)c;
|
||||
}
|
||||
return s;
|
||||
|
||||
}
|
||||
|
||||
void *__libqasan_memchr(const void *s, int c, size_t n) {
|
||||
|
||||
unsigned char *m = (unsigned char *)s;
|
||||
size_t i;
|
||||
for (i = 0; i < n; ++i)
|
||||
if (m[i] == (unsigned char)c) return &m[i];
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (m[i] == (unsigned char)c) { return &m[i]; }
|
||||
}
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
void *__libqasan_memrchr(const void *s, int c, size_t n) {
|
||||
|
||||
unsigned char *m = (unsigned char *)s;
|
||||
long i;
|
||||
for (i = n; i >= 0; --i)
|
||||
if (m[i] == (unsigned char)c) return &m[i];
|
||||
for (i = n; i >= 0; --i) {
|
||||
if (m[i] == (unsigned char)c) { return &m[i]; }
|
||||
}
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
size_t __libqasan_strlen(const char *s) {
|
||||
|
||||
const char *i = s;
|
||||
while (*(i++))
|
||||
;
|
||||
return i - s - 1;
|
||||
|
||||
}
|
||||
|
||||
size_t __libqasan_strnlen(const char *s, size_t len) {
|
||||
|
||||
size_t r = 0;
|
||||
while (len-- && *(s++))
|
||||
while (len-- && *(s++)) {
|
||||
++r;
|
||||
}
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
int __libqasan_strcmp(const char *str1, const char *str2) {
|
||||
|
||||
while (1) {
|
||||
|
||||
const unsigned char c1 = *str1, c2 = *str2;
|
||||
|
||||
if (c1 != c2) return c1 - c2;
|
||||
if (!c1) return 0;
|
||||
if (c1 != c2) { return c1 - c2; }
|
||||
if (!c1) { return 0; }
|
||||
str1++;
|
||||
str2++;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int __libqasan_strncmp(const char *str1, const char *str2, size_t len) {
|
||||
|
||||
while (len--) {
|
||||
|
||||
unsigned char c1 = *str1, c2 = *str2;
|
||||
|
||||
if (c1 != c2) return c1 - c2;
|
||||
if (!c1) return 0;
|
||||
if (c1 != c2) { return c1 - c2; }
|
||||
if (!c1) { return 0; }
|
||||
str1++;
|
||||
str2++;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int __libqasan_strcasecmp(const char *str1, const char *str2) {
|
||||
|
||||
while (1) {
|
||||
|
||||
const unsigned char c1 = tolower(*str1), c2 = tolower(*str2);
|
||||
|
||||
if (c1 != c2) return c1 - c2;
|
||||
if (!c1) return 0;
|
||||
if (c1 != c2) { return c1 - c2; }
|
||||
if (!c1) { return 0; }
|
||||
str1++;
|
||||
str2++;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int __libqasan_strncasecmp(const char *str1, const char *str2, size_t len) {
|
||||
|
||||
while (len--) {
|
||||
|
||||
const unsigned char c1 = tolower(*str1), c2 = tolower(*str2);
|
||||
|
||||
if (c1 != c2) return c1 - c2;
|
||||
if (!c1) return 0;
|
||||
if (c1 != c2) { return c1 - c2; }
|
||||
if (!c1) { return 0; }
|
||||
str1++;
|
||||
str2++;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int __libqasan_memcmp(const void *mem1, const void *mem2, size_t len) {
|
||||
|
||||
const char *strmem1 = (const char *)mem1;
|
||||
const char *strmem2 = (const char *)mem2;
|
||||
|
||||
while (len--) {
|
||||
|
||||
const unsigned char c1 = *strmem1, c2 = *strmem2;
|
||||
if (c1 != c2) return (c1 > c2) ? 1 : -1;
|
||||
strmem1++;
|
||||
strmem2++;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int __libqasan_bcmp(const void *mem1, const void *mem2, size_t len) {
|
||||
|
||||
const char *strmem1 = (const char *)mem1;
|
||||
const char *strmem2 = (const char *)mem2;
|
||||
|
||||
while (len--) {
|
||||
|
||||
int diff = *strmem1 ^ *strmem2;
|
||||
if (diff != 0) return 1;
|
||||
strmem1++;
|
||||
strmem2++;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
char *__libqasan_strstr(const char *haystack, const char *needle) {
|
||||
|
||||
do {
|
||||
|
||||
const char *n = needle;
|
||||
const char *h = haystack;
|
||||
|
||||
while (*n && *h && *n == *h)
|
||||
n++, h++;
|
||||
while (*n && *h && *n == *h) {
|
||||
n++;
|
||||
h++;
|
||||
}
|
||||
|
||||
if (!*n) return (char *)haystack;
|
||||
if (!*n) { return (char *)haystack; }
|
||||
|
||||
} while (*(haystack++));
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
char *__libqasan_strcasestr(const char *haystack, const char *needle) {
|
||||
|
||||
do {
|
||||
|
||||
const char *n = needle;
|
||||
const char *h = haystack;
|
||||
|
||||
while (*n && *h && tolower(*n) == tolower(*h))
|
||||
n++, h++;
|
||||
while (*n && *h && tolower(*n) == tolower(*h)) {
|
||||
n++;
|
||||
h++;
|
||||
}
|
||||
|
||||
if (!*n) return (char *)haystack;
|
||||
|
||||
} while (*(haystack++));
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void *__libqasan_memmem(const void *haystack, size_t haystack_len,
|
||||
const void *needle, size_t needle_len) {
|
||||
|
||||
const char *n = (const char *)needle;
|
||||
const char *h = (const char *)haystack;
|
||||
if (haystack_len < needle_len) return 0;
|
||||
@ -264,76 +227,59 @@ void *__libqasan_memmem(const void *haystack, size_t haystack_len,
|
||||
const char *end = h + (haystack_len - needle_len);
|
||||
|
||||
do {
|
||||
|
||||
if (*h == *n) {
|
||||
|
||||
if (memcmp(h, n, needle_len) == 0) return (void *)h;
|
||||
|
||||
}
|
||||
|
||||
} while (++h <= end);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
char *__libqasan_strchr(const char *s, int c) {
|
||||
|
||||
while (*s != (char)c)
|
||||
if (!*s++) return 0;
|
||||
while (*s != (char)c) {
|
||||
if (!*s++) { return 0; }
|
||||
}
|
||||
return (char *)s;
|
||||
|
||||
}
|
||||
|
||||
char *__libqasan_strrchr(const char *s, int c) {
|
||||
|
||||
char *r = NULL;
|
||||
do
|
||||
if (*s == (char)c) r = (char *)s;
|
||||
while (*s++);
|
||||
do {
|
||||
if (*s == (char)c) { r = (char *)s; }
|
||||
} while (*s++);
|
||||
|
||||
return r;
|
||||
|
||||
}
|
||||
|
||||
size_t __libqasan_wcslen(const wchar_t *s) {
|
||||
|
||||
size_t len = 0;
|
||||
|
||||
while (s[len] != L'\0') {
|
||||
|
||||
if (s[++len] == L'\0') return len;
|
||||
if (s[++len] == L'\0') return len;
|
||||
if (s[++len] == L'\0') return len;
|
||||
++len;
|
||||
|
||||
}
|
||||
|
||||
return len;
|
||||
|
||||
}
|
||||
|
||||
wchar_t *__libqasan_wcscpy(wchar_t *d, const wchar_t *s) {
|
||||
|
||||
wchar_t *a = d;
|
||||
while ((*d++ = *s++))
|
||||
;
|
||||
return a;
|
||||
|
||||
}
|
||||
|
||||
int __libqasan_wcscmp(const wchar_t *s1, const wchar_t *s2) {
|
||||
|
||||
wchar_t c1, c2;
|
||||
do {
|
||||
|
||||
c1 = *s1++;
|
||||
c2 = *s2++;
|
||||
if (c2 == L'\0') return c1 - c2;
|
||||
if (c2 == L'\0') { return c1 - c2; }
|
||||
|
||||
} while (c1 == c2);
|
||||
|
||||
return c1 < c2 ? -1 : 1;
|
||||
|
||||
}
|
||||
|
||||
|
@ -43,17 +43,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define X_GET_FNDECL(type, name) type name
|
||||
#define GET_FNDECL(x) X_GET_FNDECL x
|
||||
|
||||
#define HOOK_UNINSTRUMENT(rettype, name, ...) \
|
||||
rettype (*__lq_libc_##name)(MAP_LIST(GET_FNTYPE, __VA_ARGS__)); \
|
||||
rettype name(MAP_LIST(GET_FNDECL, __VA_ARGS__)) { \
|
||||
\
|
||||
if (!(__lq_libc_##name)) __lq_libc_##name = ASSERT_DLSYM(name); \
|
||||
int state = QASAN_SWAP(QASAN_DISABLED); \
|
||||
rettype r = __lq_libc_##name(MAP_LIST(GET_FNPAR, __VA_ARGS__)); \
|
||||
QASAN_SWAP(state); \
|
||||
\
|
||||
return r; \
|
||||
\
|
||||
#define HOOK_UNINSTRUMENT(rettype, name, ...) \
|
||||
rettype (*__lq_libc_##name)(MAP_LIST(GET_FNTYPE, __VA_ARGS__)); \
|
||||
rettype name(MAP_LIST(GET_FNDECL, __VA_ARGS__)) { \
|
||||
if (!(__lq_libc_##name)) { __lq_libc_##name = ASSERT_DLSYM(name); } \
|
||||
int state = QASAN_SWAP(QASAN_DISABLED); \
|
||||
rettype r = __lq_libc_##name(MAP_LIST(GET_FNPAR, __VA_ARGS__)); \
|
||||
QASAN_SWAP(state); \
|
||||
\
|
||||
return r; \
|
||||
}
|
||||
|
||||
HOOK_UNINSTRUMENT(char *, getenv, (const char *, name))
|
||||
@ -80,4 +78,3 @@ HOOK_UNINSTRUMENT(int, getpwnam_r, (const char *, name), (struct passwd *, pwd),
|
||||
HOOK_UNINSTRUMENT(int, getpwuid_r, (uid_t, uid), (struct passwd *, pwd), (char
|
||||
*, buf), (size_t, buflen), (struct passwd **, result))
|
||||
*/
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -38,12 +38,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define TARGET_FMT_ld "%" PRId64
|
||||
|
||||
#ifndef ASAN_NAME_STR
|
||||
#define ASAN_NAME_STR "AddressSanitizer"
|
||||
#define ASAN_NAME_STR "AddressSanitizer"
|
||||
#endif
|
||||
|
||||
#define HIGH_SHADOW_ADDR ((void*)0x02008fff7000ULL)
|
||||
#define LOW_SHADOW_ADDR ((void*)0x00007fff8000ULL)
|
||||
#define GAP_SHADOW_ADDR ((void*)0x00008fff7000)
|
||||
#define HIGH_SHADOW_ADDR ((void *)0x02008fff7000ULL)
|
||||
#define LOW_SHADOW_ADDR ((void *)0x00007fff8000ULL)
|
||||
#define GAP_SHADOW_ADDR ((void *)0x00008fff7000)
|
||||
|
||||
#define HIGH_SHADOW_SIZE (0xdfff0000fffULL)
|
||||
#define LOW_SHADOW_SIZE (0xfffefffULL)
|
||||
@ -82,32 +82,28 @@ enum {
|
||||
};
|
||||
|
||||
struct call_context {
|
||||
|
||||
target_ulong* addresses;
|
||||
target_ulong *addresses;
|
||||
uint32_t tid;
|
||||
uint32_t size;
|
||||
|
||||
};
|
||||
|
||||
struct chunk_info {
|
||||
|
||||
target_ulong start;
|
||||
target_ulong end;
|
||||
struct call_context* alloc_ctx;
|
||||
struct call_context* free_ctx; // NULL if chunk is allocated
|
||||
|
||||
struct call_context *alloc_ctx;
|
||||
struct call_context *free_ctx; // NULL if chunk is allocated
|
||||
};
|
||||
|
||||
extern void* __ag_high_shadow;
|
||||
extern void* __ag_low_shadow;
|
||||
extern void *__ag_high_shadow;
|
||||
extern void *__ag_low_shadow;
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
// Virtual functions, you have to implement them
|
||||
// ------------------------------------------------------------------------- //
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void asan_giovese_populate_context(struct call_context* ctx, target_ulong pc);
|
||||
char* asan_giovese_printaddr(target_ulong addr);
|
||||
void asan_giovese_populate_context(struct call_context *ctx, target_ulong pc);
|
||||
char *asan_giovese_printaddr(target_ulong addr);
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// ------------------------------------------------------------------------- //
|
||||
@ -118,25 +114,25 @@ void asan_giovese_init(void);
|
||||
|
||||
// this has to be fast, ptr is an host pointer
|
||||
|
||||
int asan_giovese_load1(void* ptr);
|
||||
int asan_giovese_load2(void* ptr);
|
||||
int asan_giovese_load4(void* ptr);
|
||||
int asan_giovese_load8(void* ptr);
|
||||
int asan_giovese_store1(void* ptr);
|
||||
int asan_giovese_store2(void* ptr);
|
||||
int asan_giovese_store4(void* ptr);
|
||||
int asan_giovese_store8(void* ptr);
|
||||
int asan_giovese_loadN(void* ptr, size_t n);
|
||||
int asan_giovese_storeN(void* ptr, size_t n);
|
||||
int asan_giovese_load1(void *ptr);
|
||||
int asan_giovese_load2(void *ptr);
|
||||
int asan_giovese_load4(void *ptr);
|
||||
int asan_giovese_load8(void *ptr);
|
||||
int asan_giovese_store1(void *ptr);
|
||||
int asan_giovese_store2(void *ptr);
|
||||
int asan_giovese_store4(void *ptr);
|
||||
int asan_giovese_store8(void *ptr);
|
||||
int asan_giovese_loadN(void *ptr, size_t n);
|
||||
int asan_giovese_storeN(void *ptr, size_t n);
|
||||
int asan_giovese_guest_loadN(target_ulong addr, size_t n);
|
||||
int asan_giovese_guest_storeN(target_ulong addr, size_t n);
|
||||
|
||||
int asan_giovese_poison_region(void* ptr, size_t n,
|
||||
uint8_t poison_byte);
|
||||
int asan_giovese_user_poison_region(void* ptr, size_t n);
|
||||
int asan_giovese_unpoison_region(void* ptr, size_t n);
|
||||
int asan_giovese_poison_region(void *ptr, size_t n, uint8_t poison_byte);
|
||||
int asan_giovese_user_poison_region(void *ptr, size_t n);
|
||||
int asan_giovese_unpoison_region(void *ptr, size_t n);
|
||||
|
||||
int asan_giovese_poison_guest_region(target_ulong addr, size_t n, uint8_t poison_byte);
|
||||
int asan_giovese_poison_guest_region(target_ulong addr, size_t n,
|
||||
uint8_t poison_byte);
|
||||
int asan_giovese_user_poison_guest_region(target_ulong addr, size_t n);
|
||||
int asan_giovese_unpoison_guest_region(target_ulong addr, size_t n);
|
||||
|
||||
@ -151,10 +147,9 @@ int asan_giovese_deadly_signal(int signum, target_ulong addr, target_ulong pc,
|
||||
|
||||
int asan_giovese_badfree(target_ulong addr, target_ulong pc);
|
||||
|
||||
struct chunk_info* asan_giovese_alloc_search(target_ulong query);
|
||||
struct chunk_info *asan_giovese_alloc_search(target_ulong query);
|
||||
void asan_giovese_alloc_remove(target_ulong start, target_ulong end);
|
||||
void asan_giovese_alloc_insert(target_ulong start, target_ulong end,
|
||||
struct call_context* alloc_ctx);
|
||||
struct call_context *alloc_ctx);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef __INT_COMPILER_H__
|
||||
#define __INT_COMPILER_H__
|
||||
#ifndef __INT_COMPILER_H__
|
||||
#define __INT_COMPILER_H__
|
||||
|
||||
/**
|
||||
* container_of - cast a member of a structure out to the containing structure
|
||||
@ -9,9 +9,11 @@
|
||||
*
|
||||
*/
|
||||
#ifndef container_of
|
||||
#define container_of(ptr, type, member) ({ \
|
||||
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
|
||||
(type *)( (char *)__mptr - offsetof(type,member) );})
|
||||
#define container_of(ptr, type, member) \
|
||||
({ \
|
||||
const typeof(((type *)0)->member) *__mptr = (ptr); \
|
||||
(type *)((char *)__mptr - offsetof(type, member)); \
|
||||
})
|
||||
#endif
|
||||
|
||||
#endif /* __INT_COMPILER_H__ */
|
||||
#endif /* __INT_COMPILER_H__ */
|
||||
|
@ -39,155 +39,138 @@
|
||||
* (interval_tree.h) would work for you...
|
||||
*/
|
||||
|
||||
#define INTERVAL_TREE_DEFINE(ITSTRUCT, ITRB, ITTYPE, ITSUBTREE, \
|
||||
ITSTART, ITLAST, ITSTATIC, ITPREFIX) \
|
||||
\
|
||||
/* Callbacks for augmented rbtree insert and remove */ \
|
||||
\
|
||||
static inline ITTYPE ITPREFIX ## _compute_subtree_last(ITSTRUCT *node) \
|
||||
{ \
|
||||
ITTYPE max = ITLAST(node), subtree_last; \
|
||||
if (node->ITRB.rb_left) { \
|
||||
subtree_last = rb_entry(node->ITRB.rb_left, \
|
||||
ITSTRUCT, ITRB)->ITSUBTREE; \
|
||||
if (max < subtree_last) \
|
||||
max = subtree_last; \
|
||||
} \
|
||||
if (node->ITRB.rb_right) { \
|
||||
subtree_last = rb_entry(node->ITRB.rb_right, \
|
||||
ITSTRUCT, ITRB)->ITSUBTREE; \
|
||||
if (max < subtree_last) \
|
||||
max = subtree_last; \
|
||||
} \
|
||||
return max; \
|
||||
} \
|
||||
\
|
||||
RB_DECLARE_CALLBACKS(static, ITPREFIX ## _augment, ITSTRUCT, ITRB, \
|
||||
ITTYPE, ITSUBTREE, ITPREFIX ## _compute_subtree_last) \
|
||||
\
|
||||
/* Insert / remove interval nodes from the tree */ \
|
||||
\
|
||||
ITSTATIC void ITPREFIX ## _insert(ITSTRUCT *node, struct rb_root *root) \
|
||||
{ \
|
||||
struct rb_node **link = &root->rb_node, *rb_parent = NULL; \
|
||||
ITTYPE start = ITSTART(node), last = ITLAST(node); \
|
||||
ITSTRUCT *parent; \
|
||||
\
|
||||
while (*link) { \
|
||||
rb_parent = *link; \
|
||||
parent = rb_entry(rb_parent, ITSTRUCT, ITRB); \
|
||||
if (parent->ITSUBTREE < last) \
|
||||
parent->ITSUBTREE = last; \
|
||||
if (start < ITSTART(parent)) \
|
||||
link = &parent->ITRB.rb_left; \
|
||||
else \
|
||||
link = &parent->ITRB.rb_right; \
|
||||
} \
|
||||
\
|
||||
node->ITSUBTREE = last; \
|
||||
rb_link_node(&node->ITRB, rb_parent, link); \
|
||||
rb_insert_augmented(&node->ITRB, root, &ITPREFIX ## _augment); \
|
||||
} \
|
||||
\
|
||||
ITSTATIC void ITPREFIX ## _remove(ITSTRUCT *node, struct rb_root *root) \
|
||||
{ \
|
||||
rb_erase_augmented(&node->ITRB, root, &ITPREFIX ## _augment); \
|
||||
} \
|
||||
\
|
||||
/* \
|
||||
* Iterate over intervals intersecting [start;last] \
|
||||
* \
|
||||
* Note that a node's interval intersects [start;last] iff: \
|
||||
* Cond1: ITSTART(node) <= last \
|
||||
* and \
|
||||
* Cond2: start <= ITLAST(node) \
|
||||
*/ \
|
||||
\
|
||||
static ITSTRUCT * \
|
||||
ITPREFIX ## _subtree_search(ITSTRUCT *node, ITTYPE start, ITTYPE last) \
|
||||
{ \
|
||||
while (true) { \
|
||||
/* \
|
||||
* Loop invariant: start <= node->ITSUBTREE \
|
||||
* (Cond2 is satisfied by one of the subtree nodes) \
|
||||
*/ \
|
||||
if (node->ITRB.rb_left) { \
|
||||
ITSTRUCT *left = rb_entry(node->ITRB.rb_left, \
|
||||
ITSTRUCT, ITRB); \
|
||||
if (start <= left->ITSUBTREE) { \
|
||||
/* \
|
||||
* Some nodes in left subtree satisfy Cond2. \
|
||||
* Iterate to find the leftmost such node N. \
|
||||
* If it also satisfies Cond1, that's the \
|
||||
* match we are looking for. Otherwise, there \
|
||||
* is no matching interval as nodes to the \
|
||||
* right of N can't satisfy Cond1 either. \
|
||||
*/ \
|
||||
node = left; \
|
||||
continue; \
|
||||
} \
|
||||
} \
|
||||
if (ITSTART(node) <= last) { /* Cond1 */ \
|
||||
if (start <= ITLAST(node)) /* Cond2 */ \
|
||||
return node; /* node is leftmost match */ \
|
||||
if (node->ITRB.rb_right) { \
|
||||
node = rb_entry(node->ITRB.rb_right, \
|
||||
ITSTRUCT, ITRB); \
|
||||
if (start <= node->ITSUBTREE) \
|
||||
continue; \
|
||||
} \
|
||||
} \
|
||||
return NULL; /* No match */ \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
ITSTATIC ITSTRUCT * \
|
||||
ITPREFIX ## _iter_first(struct rb_root *root, ITTYPE start, ITTYPE last) \
|
||||
{ \
|
||||
ITSTRUCT *node; \
|
||||
\
|
||||
if (!root->rb_node) \
|
||||
return NULL; \
|
||||
node = rb_entry(root->rb_node, ITSTRUCT, ITRB); \
|
||||
if (node->ITSUBTREE < start) \
|
||||
return NULL; \
|
||||
return ITPREFIX ## _subtree_search(node, start, last); \
|
||||
} \
|
||||
\
|
||||
ITSTATIC ITSTRUCT * \
|
||||
ITPREFIX ## _iter_next(ITSTRUCT *node, ITTYPE start, ITTYPE last) \
|
||||
{ \
|
||||
struct rb_node *rb = node->ITRB.rb_right, *prev; \
|
||||
\
|
||||
while (true) { \
|
||||
/* \
|
||||
* Loop invariants: \
|
||||
* Cond1: ITSTART(node) <= last \
|
||||
* rb == node->ITRB.rb_right \
|
||||
* \
|
||||
* First, search right subtree if suitable \
|
||||
*/ \
|
||||
if (rb) { \
|
||||
ITSTRUCT *right = rb_entry(rb, ITSTRUCT, ITRB); \
|
||||
if (start <= right->ITSUBTREE) \
|
||||
return ITPREFIX ## _subtree_search(right, \
|
||||
start, last); \
|
||||
} \
|
||||
\
|
||||
/* Move up the tree until we come from a node's left child */ \
|
||||
do { \
|
||||
rb = rb_parent(&node->ITRB); \
|
||||
if (!rb) \
|
||||
return NULL; \
|
||||
prev = &node->ITRB; \
|
||||
node = rb_entry(rb, ITSTRUCT, ITRB); \
|
||||
rb = node->ITRB.rb_right; \
|
||||
} while (prev == rb); \
|
||||
\
|
||||
/* Check if the node intersects [start;last] */ \
|
||||
if (last < ITSTART(node)) /* !Cond1 */ \
|
||||
return NULL; \
|
||||
else if (start <= ITLAST(node)) /* Cond2 */ \
|
||||
return node; \
|
||||
} \
|
||||
}
|
||||
#define INTERVAL_TREE_DEFINE(ITSTRUCT, ITRB, ITTYPE, ITSUBTREE, ITSTART, \
|
||||
ITLAST, ITSTATIC, ITPREFIX) \
|
||||
\
|
||||
/* Callbacks for augmented rbtree insert and remove */ \
|
||||
\
|
||||
static inline ITTYPE ITPREFIX##_compute_subtree_last(ITSTRUCT *node) { \
|
||||
ITTYPE max = ITLAST(node), subtree_last; \
|
||||
if (node->ITRB.rb_left) { \
|
||||
subtree_last = rb_entry(node->ITRB.rb_left, ITSTRUCT, ITRB)->ITSUBTREE; \
|
||||
if (max < subtree_last) { max = subtree_last; } \
|
||||
} \
|
||||
if (node->ITRB.rb_right) { \
|
||||
subtree_last = rb_entry(node->ITRB.rb_right, ITSTRUCT, ITRB)->ITSUBTREE; \
|
||||
if (max < subtree_last) max = subtree_last; \
|
||||
} \
|
||||
return max; \
|
||||
} \
|
||||
\
|
||||
RB_DECLARE_CALLBACKS(static, ITPREFIX##_augment, ITSTRUCT, ITRB, ITTYPE, \
|
||||
ITSUBTREE, ITPREFIX##_compute_subtree_last) \
|
||||
\
|
||||
/* Insert / remove interval nodes from the tree */ \
|
||||
\
|
||||
ITSTATIC void ITPREFIX##_insert(ITSTRUCT *node, struct rb_root *root) { \
|
||||
struct rb_node **link = &root->rb_node, *rb_parent = NULL; \
|
||||
ITTYPE start = ITSTART(node), last = ITLAST(node); \
|
||||
ITSTRUCT *parent; \
|
||||
\
|
||||
while (*link) { \
|
||||
rb_parent = *link; \
|
||||
parent = rb_entry(rb_parent, ITSTRUCT, ITRB); \
|
||||
if (parent->ITSUBTREE < last) parent->ITSUBTREE = last; \
|
||||
if (start < ITSTART(parent)) \
|
||||
link = &parent->ITRB.rb_left; \
|
||||
else \
|
||||
link = &parent->ITRB.rb_right; \
|
||||
} \
|
||||
\
|
||||
node->ITSUBTREE = last; \
|
||||
rb_link_node(&node->ITRB, rb_parent, link); \
|
||||
rb_insert_augmented(&node->ITRB, root, &ITPREFIX##_augment); \
|
||||
} \
|
||||
\
|
||||
ITSTATIC void ITPREFIX##_remove(ITSTRUCT *node, struct rb_root *root) { \
|
||||
rb_erase_augmented(&node->ITRB, root, &ITPREFIX##_augment); \
|
||||
} \
|
||||
\
|
||||
/* \
|
||||
* Iterate over intervals intersecting [start;last] \
|
||||
* \
|
||||
* Note that a node's interval intersects [start;last] iff: \
|
||||
* Cond1: ITSTART(node) <= last \
|
||||
* and \
|
||||
* Cond2: start <= ITLAST(node) \
|
||||
*/ \
|
||||
\
|
||||
static ITSTRUCT *ITPREFIX##_subtree_search(ITSTRUCT *node, ITTYPE start, \
|
||||
ITTYPE last) { \
|
||||
while (true) { \
|
||||
/* \
|
||||
* Loop invariant: start <= node->ITSUBTREE \
|
||||
* (Cond2 is satisfied by one of the subtree nodes) \
|
||||
*/ \
|
||||
if (node->ITRB.rb_left) { \
|
||||
ITSTRUCT *left = rb_entry(node->ITRB.rb_left, ITSTRUCT, ITRB); \
|
||||
if (start <= left->ITSUBTREE) { \
|
||||
/* \
|
||||
* Some nodes in left subtree satisfy Cond2. \
|
||||
* Iterate to find the leftmost such node N. \
|
||||
* If it also satisfies Cond1, that's the \
|
||||
* match we are looking for. Otherwise, there \
|
||||
* is no matching interval as nodes to the \
|
||||
* right of N can't satisfy Cond1 either. \
|
||||
*/ \
|
||||
node = left; \
|
||||
continue; \
|
||||
} \
|
||||
} \
|
||||
if (ITSTART(node) <= last) { /* Cond1 */ \
|
||||
if (start <= ITLAST(node)) /* Cond2 */ \
|
||||
return node; /* node is leftmost match */ \
|
||||
if (node->ITRB.rb_right) { \
|
||||
node = rb_entry(node->ITRB.rb_right, ITSTRUCT, ITRB); \
|
||||
if (start <= node->ITSUBTREE) continue; \
|
||||
} \
|
||||
} \
|
||||
return NULL; /* No match */ \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
ITSTATIC ITSTRUCT *ITPREFIX##_iter_first(struct rb_root *root, ITTYPE start, \
|
||||
ITTYPE last) { \
|
||||
ITSTRUCT *node; \
|
||||
\
|
||||
if (!root->rb_node) return NULL; \
|
||||
node = rb_entry(root->rb_node, ITSTRUCT, ITRB); \
|
||||
if (node->ITSUBTREE < start) return NULL; \
|
||||
return ITPREFIX##_subtree_search(node, start, last); \
|
||||
} \
|
||||
\
|
||||
ITSTATIC ITSTRUCT *ITPREFIX##_iter_next(ITSTRUCT *node, ITTYPE start, \
|
||||
ITTYPE last) { \
|
||||
struct rb_node *rb = node->ITRB.rb_right, *prev; \
|
||||
\
|
||||
while (true) { \
|
||||
/* \
|
||||
* Loop invariants: \
|
||||
* Cond1: ITSTART(node) <= last \
|
||||
* rb == node->ITRB.rb_right \
|
||||
* \
|
||||
* First, search right subtree if suitable \
|
||||
*/ \
|
||||
if (rb) { \
|
||||
ITSTRUCT *right = rb_entry(rb, ITSTRUCT, ITRB); \
|
||||
if (start <= right->ITSUBTREE) \
|
||||
return ITPREFIX##_subtree_search(right, start, last); \
|
||||
} \
|
||||
\
|
||||
/* Move up the tree until we come from a node's left child */ \
|
||||
do { \
|
||||
rb = rb_parent(&node->ITRB); \
|
||||
if (!rb) { return NULL; } \
|
||||
prev = &node->ITRB; \
|
||||
node = rb_entry(rb, ITSTRUCT, ITRB); \
|
||||
rb = node->ITRB.rb_right; \
|
||||
} while (prev == rb); \
|
||||
\
|
||||
/* Check if the node intersects [start;last] */ \
|
||||
if (last < ITSTART(node)) { /* !Cond1 */ \
|
||||
return NULL; \
|
||||
} else if (start <= ITLAST(node)) { /* Cond2 */ \
|
||||
return node; \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
Red Black Trees
|
||||
(C) 1999 Andrea Arcangeli <andrea@suse.de>
|
||||
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
@ -26,42 +26,40 @@
|
||||
See Documentation/rbtree.txt for documentation and samples.
|
||||
*/
|
||||
|
||||
#ifndef _LINUX_RBTREE_H
|
||||
#define _LINUX_RBTREE_H
|
||||
#ifndef _LINUX_RBTREE_H
|
||||
#define _LINUX_RBTREE_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include "compiler.h"
|
||||
|
||||
struct rb_node {
|
||||
unsigned long __rb_parent_color;
|
||||
struct rb_node *rb_right;
|
||||
struct rb_node *rb_left;
|
||||
unsigned long __rb_parent_color;
|
||||
struct rb_node *rb_right;
|
||||
struct rb_node *rb_left;
|
||||
} __attribute__((aligned(sizeof(long))));
|
||||
/* The alignment might seem pointless, but allegedly CRIS needs it */
|
||||
/* The alignment might seem pointless, but allegedly CRIS needs it */
|
||||
|
||||
struct rb_root {
|
||||
struct rb_node *rb_node;
|
||||
struct rb_node *rb_node;
|
||||
};
|
||||
|
||||
#define rb_parent(r) ((struct rb_node *)((r)->__rb_parent_color & ~3))
|
||||
|
||||
#define rb_parent(r) ((struct rb_node *)((r)->__rb_parent_color & ~3))
|
||||
#define RB_ROOT \
|
||||
(struct rb_root) { \
|
||||
NULL, \
|
||||
}
|
||||
#define rb_entry(ptr, type, member) container_of(ptr, type, member)
|
||||
|
||||
#define RB_ROOT (struct rb_root) { NULL, }
|
||||
#define rb_entry(ptr, type, member) container_of(ptr, type, member)
|
||||
|
||||
#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
|
||||
#define RB_EMPTY_ROOT(root) ((root)->rb_node == NULL)
|
||||
|
||||
/* 'empty' nodes are nodes that are known not to be inserted in an rbtree */
|
||||
#define RB_EMPTY_NODE(node) \
|
||||
((node)->__rb_parent_color == (unsigned long)(node))
|
||||
#define RB_CLEAR_NODE(node) \
|
||||
((node)->__rb_parent_color = (unsigned long)(node))
|
||||
|
||||
#define RB_EMPTY_NODE(node) ((node)->__rb_parent_color == (unsigned long)(node))
|
||||
#define RB_CLEAR_NODE(node) ((node)->__rb_parent_color = (unsigned long)(node))
|
||||
|
||||
extern void rb_insert_color(struct rb_node *, struct rb_root *);
|
||||
extern void rb_erase(struct rb_node *, struct rb_root *);
|
||||
|
||||
|
||||
/* Find logical next and previous nodes in a tree */
|
||||
extern struct rb_node *rb_next(const struct rb_node *);
|
||||
extern struct rb_node *rb_prev(const struct rb_node *);
|
||||
@ -73,22 +71,22 @@ extern struct rb_node *rb_first_postorder(const struct rb_root *);
|
||||
extern struct rb_node *rb_next_postorder(const struct rb_node *);
|
||||
|
||||
/* Fast replacement of a single node without remove/rebalance/add/rebalance */
|
||||
extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
|
||||
struct rb_root *root);
|
||||
extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
|
||||
struct rb_root *root);
|
||||
|
||||
static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
|
||||
struct rb_node ** rb_link)
|
||||
{
|
||||
node->__rb_parent_color = (unsigned long)parent;
|
||||
node->rb_left = node->rb_right = NULL;
|
||||
static inline void rb_link_node(struct rb_node *node, struct rb_node *parent,
|
||||
struct rb_node **rb_link) {
|
||||
node->__rb_parent_color = (unsigned long)parent;
|
||||
node->rb_left = node->rb_right = NULL;
|
||||
|
||||
*rb_link = node;
|
||||
*rb_link = node;
|
||||
}
|
||||
|
||||
#define rb_entry_safe(ptr, type, member) \
|
||||
({ typeof(ptr) ____ptr = (ptr); \
|
||||
____ptr ? rb_entry(____ptr, type, member) : NULL; \
|
||||
})
|
||||
#define rb_entry_safe(ptr, type, member) \
|
||||
({ \
|
||||
typeof(ptr) ____ptr = (ptr); \
|
||||
____ptr ? rb_entry(____ptr, type, member) : NULL; \
|
||||
})
|
||||
|
||||
/**
|
||||
* rbtree_postorder_for_each_entry_safe - iterate over rb_root in post order of
|
||||
@ -99,10 +97,13 @@ static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
|
||||
* @root: 'rb_root *' of the rbtree.
|
||||
* @field: the name of the rb_node field within 'type'.
|
||||
*/
|
||||
#define rbtree_postorder_for_each_entry_safe(pos, n, root, field) \
|
||||
for (pos = rb_entry_safe(rb_first_postorder(root), typeof(*pos), field); \
|
||||
pos && ({ n = rb_entry_safe(rb_next_postorder(&pos->field), \
|
||||
typeof(*pos), field); 1; }); \
|
||||
pos = n)
|
||||
#define rbtree_postorder_for_each_entry_safe(pos, n, root, field) \
|
||||
for (pos = rb_entry_safe(rb_first_postorder(root), typeof(*pos), field); \
|
||||
pos && ({ \
|
||||
n = rb_entry_safe(rb_next_postorder(&pos->field), typeof(*pos), \
|
||||
field); \
|
||||
1; \
|
||||
}); \
|
||||
pos = n)
|
||||
|
||||
#endif /* _LINUX_RBTREE_H */
|
||||
#endif /* _LINUX_RBTREE_H */
|
||||
|
@ -416,10 +416,12 @@ struct rb_node *rb_first(const struct rb_root *root)
|
||||
struct rb_node *n;
|
||||
|
||||
n = root->rb_node;
|
||||
if (!n)
|
||||
if (!n) {
|
||||
return NULL;
|
||||
while (n->rb_left)
|
||||
}
|
||||
while (n->rb_left) {
|
||||
n = n->rb_left;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
@ -428,10 +430,12 @@ struct rb_node *rb_last(const struct rb_root *root)
|
||||
struct rb_node *n;
|
||||
|
||||
n = root->rb_node;
|
||||
if (!n)
|
||||
if (!n) {
|
||||
return NULL;
|
||||
while (n->rb_right)
|
||||
}
|
||||
while (n->rb_right) {
|
||||
n = n->rb_right;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
@ -448,8 +452,9 @@ struct rb_node *rb_next(const struct rb_node *node)
|
||||
*/
|
||||
if (node->rb_right) {
|
||||
node = node->rb_right;
|
||||
while (node->rb_left)
|
||||
while (node->rb_left) {
|
||||
node=node->rb_left;
|
||||
}
|
||||
return (struct rb_node *)node;
|
||||
}
|
||||
|
||||
@ -460,8 +465,9 @@ struct rb_node *rb_next(const struct rb_node *node)
|
||||
* parent, keep going up. First time it's a left-hand child of its
|
||||
* parent, said parent is our 'next' node.
|
||||
*/
|
||||
while ((parent = rb_parent(node)) && node == parent->rb_right)
|
||||
while ((parent = rb_parent(node)) && node == parent->rb_right) {
|
||||
node = parent;
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
@ -479,8 +485,9 @@ struct rb_node *rb_prev(const struct rb_node *node)
|
||||
*/
|
||||
if (node->rb_left) {
|
||||
node = node->rb_left;
|
||||
while (node->rb_right)
|
||||
while (node->rb_right) {
|
||||
node=node->rb_right;
|
||||
}
|
||||
return (struct rb_node *)node;
|
||||
}
|
||||
|
||||
@ -488,8 +495,9 @@ struct rb_node *rb_prev(const struct rb_node *node)
|
||||
* No left-hand children. Go up till we find an ancestor which
|
||||
* is a right-hand child of its parent.
|
||||
*/
|
||||
while ((parent = rb_parent(node)) && node == parent->rb_left)
|
||||
while ((parent = rb_parent(node)) && node == parent->rb_left) {
|
||||
node = parent;
|
||||
}
|
||||
|
||||
return parent;
|
||||
}
|
||||
@ -501,10 +509,12 @@ void rb_replace_node(struct rb_node *victim, struct rb_node *new,
|
||||
|
||||
/* Set the surrounding nodes to point to the replacement */
|
||||
__rb_change_child(victim, new, parent, root);
|
||||
if (victim->rb_left)
|
||||
if (victim->rb_left) {
|
||||
rb_set_parent(victim->rb_left, new);
|
||||
if (victim->rb_right)
|
||||
}
|
||||
if (victim->rb_right) {
|
||||
rb_set_parent(victim->rb_right, new);
|
||||
}
|
||||
|
||||
/* Copy the pointers/colour from the victim to the replacement */
|
||||
*new = *victim;
|
||||
@ -513,20 +523,24 @@ void rb_replace_node(struct rb_node *victim, struct rb_node *new,
|
||||
static struct rb_node *rb_left_deepest_node(const struct rb_node *node)
|
||||
{
|
||||
for (;;) {
|
||||
if (node->rb_left)
|
||||
if (node->rb_left) {
|
||||
node = node->rb_left;
|
||||
else if (node->rb_right)
|
||||
}
|
||||
else if (node->rb_right) {
|
||||
node = node->rb_right;
|
||||
else
|
||||
}
|
||||
else {
|
||||
return (struct rb_node *)node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct rb_node *rb_next_postorder(const struct rb_node *node)
|
||||
{
|
||||
const struct rb_node *parent;
|
||||
if (!node)
|
||||
if (!node) {
|
||||
return NULL;
|
||||
}
|
||||
parent = rb_parent(node);
|
||||
|
||||
/* If we're sitting on node, we've already seen our children */
|
||||
@ -542,8 +556,9 @@ struct rb_node *rb_next_postorder(const struct rb_node *node)
|
||||
|
||||
struct rb_node *rb_first_postorder(const struct rb_root *root)
|
||||
{
|
||||
if (!root->rb_node)
|
||||
if (!root->rb_node) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return rb_left_deepest_node(root->rb_node);
|
||||
}
|
||||
|
@ -39,13 +39,14 @@
|
||||
*/
|
||||
|
||||
struct rb_augment_callbacks {
|
||||
void (*propagate)(struct rb_node *node, struct rb_node *stop);
|
||||
void (*copy)(struct rb_node *old, struct rb_node *new);
|
||||
void (*rotate)(struct rb_node *old, struct rb_node *new);
|
||||
void (*propagate)(struct rb_node *node, struct rb_node *stop);
|
||||
void (*copy)(struct rb_node *old, struct rb_node *new);
|
||||
void (*rotate)(struct rb_node *old, struct rb_node *new);
|
||||
};
|
||||
|
||||
extern void __rb_insert_augmented(struct rb_node *node, struct rb_root *root,
|
||||
void (*augment_rotate)(struct rb_node *old, struct rb_node *new));
|
||||
void (*augment_rotate)(struct rb_node *old,
|
||||
struct rb_node *new));
|
||||
/*
|
||||
* Fixup the rbtree and update the augmented information when rebalancing.
|
||||
*
|
||||
@ -56,190 +57,180 @@ extern void __rb_insert_augmented(struct rb_node *node, struct rb_root *root,
|
||||
* a user provided function to update the augmented information on the
|
||||
* affected subtrees.
|
||||
*/
|
||||
static inline void
|
||||
rb_insert_augmented(struct rb_node *node, struct rb_root *root,
|
||||
const struct rb_augment_callbacks *augment)
|
||||
{
|
||||
__rb_insert_augmented(node, root, augment->rotate);
|
||||
static inline void rb_insert_augmented(
|
||||
struct rb_node *node, struct rb_root *root,
|
||||
const struct rb_augment_callbacks *augment) {
|
||||
__rb_insert_augmented(node, root, augment->rotate);
|
||||
}
|
||||
|
||||
#define RB_DECLARE_CALLBACKS(rbstatic, rbname, rbstruct, rbfield, \
|
||||
rbtype, rbaugmented, rbcompute) \
|
||||
static inline void \
|
||||
rbname ## _propagate(struct rb_node *rb, struct rb_node *stop) \
|
||||
{ \
|
||||
while (rb != stop) { \
|
||||
rbstruct *node = rb_entry(rb, rbstruct, rbfield); \
|
||||
rbtype augmented = rbcompute(node); \
|
||||
if (node->rbaugmented == augmented) \
|
||||
break; \
|
||||
node->rbaugmented = augmented; \
|
||||
rb = rb_parent(&node->rbfield); \
|
||||
} \
|
||||
} \
|
||||
static inline void \
|
||||
rbname ## _copy(struct rb_node *rb_old, struct rb_node *rb_new) \
|
||||
{ \
|
||||
rbstruct *old = rb_entry(rb_old, rbstruct, rbfield); \
|
||||
rbstruct *new = rb_entry(rb_new, rbstruct, rbfield); \
|
||||
new->rbaugmented = old->rbaugmented; \
|
||||
} \
|
||||
static void \
|
||||
rbname ## _rotate(struct rb_node *rb_old, struct rb_node *rb_new) \
|
||||
{ \
|
||||
rbstruct *old = rb_entry(rb_old, rbstruct, rbfield); \
|
||||
rbstruct *new = rb_entry(rb_new, rbstruct, rbfield); \
|
||||
new->rbaugmented = old->rbaugmented; \
|
||||
old->rbaugmented = rbcompute(old); \
|
||||
} \
|
||||
rbstatic const struct rb_augment_callbacks rbname = { \
|
||||
rbname ## _propagate, rbname ## _copy, rbname ## _rotate \
|
||||
};
|
||||
#define RB_DECLARE_CALLBACKS(rbstatic, rbname, rbstruct, rbfield, rbtype, \
|
||||
rbaugmented, rbcompute) \
|
||||
static inline void rbname##_propagate(struct rb_node *rb, \
|
||||
struct rb_node *stop) { \
|
||||
while (rb != stop) { \
|
||||
rbstruct *node = rb_entry(rb, rbstruct, rbfield); \
|
||||
rbtype augmented = rbcompute(node); \
|
||||
if (node->rbaugmented == augmented) { break; } \
|
||||
node->rbaugmented = augmented; \
|
||||
rb = rb_parent(&node->rbfield); \
|
||||
} \
|
||||
} \
|
||||
static inline void rbname##_copy(struct rb_node *rb_old, \
|
||||
struct rb_node *rb_new) { \
|
||||
rbstruct *old = rb_entry(rb_old, rbstruct, rbfield); \
|
||||
rbstruct *new = rb_entry(rb_new, rbstruct, rbfield); \
|
||||
new->rbaugmented = old->rbaugmented; \
|
||||
} \
|
||||
static void rbname##_rotate(struct rb_node *rb_old, \
|
||||
struct rb_node *rb_new) { \
|
||||
rbstruct *old = rb_entry(rb_old, rbstruct, rbfield); \
|
||||
rbstruct *new = rb_entry(rb_new, rbstruct, rbfield); \
|
||||
new->rbaugmented = old->rbaugmented; \
|
||||
old->rbaugmented = rbcompute(old); \
|
||||
} \
|
||||
rbstatic const struct rb_augment_callbacks rbname = { \
|
||||
rbname##_propagate, rbname##_copy, rbname##_rotate};
|
||||
|
||||
#define RB_RED 0
|
||||
#define RB_BLACK 1
|
||||
|
||||
#define RB_RED 0
|
||||
#define RB_BLACK 1
|
||||
#define __rb_parent(pc) ((struct rb_node *)(pc & ~3))
|
||||
|
||||
#define __rb_parent(pc) ((struct rb_node *)(pc & ~3))
|
||||
#define __rb_color(pc) ((pc)&1)
|
||||
#define __rb_is_black(pc) __rb_color(pc)
|
||||
#define __rb_is_red(pc) (!__rb_color(pc))
|
||||
#define rb_color(rb) __rb_color((rb)->__rb_parent_color)
|
||||
#define rb_is_red(rb) __rb_is_red((rb)->__rb_parent_color)
|
||||
#define rb_is_black(rb) __rb_is_black((rb)->__rb_parent_color)
|
||||
|
||||
#define __rb_color(pc) ((pc) & 1)
|
||||
#define __rb_is_black(pc) __rb_color(pc)
|
||||
#define __rb_is_red(pc) (!__rb_color(pc))
|
||||
#define rb_color(rb) __rb_color((rb)->__rb_parent_color)
|
||||
#define rb_is_red(rb) __rb_is_red((rb)->__rb_parent_color)
|
||||
#define rb_is_black(rb) __rb_is_black((rb)->__rb_parent_color)
|
||||
|
||||
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
|
||||
{
|
||||
rb->__rb_parent_color = rb_color(rb) | (unsigned long)p;
|
||||
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p) {
|
||||
rb->__rb_parent_color = rb_color(rb) | (unsigned long)p;
|
||||
}
|
||||
|
||||
static inline void rb_set_parent_color(struct rb_node *rb,
|
||||
struct rb_node *p, int color)
|
||||
{
|
||||
rb->__rb_parent_color = (unsigned long)p | color;
|
||||
static inline void rb_set_parent_color(struct rb_node *rb, struct rb_node *p,
|
||||
int color) {
|
||||
rb->__rb_parent_color = (unsigned long)p | color;
|
||||
}
|
||||
|
||||
static inline void
|
||||
__rb_change_child(struct rb_node *old, struct rb_node *new,
|
||||
struct rb_node *parent, struct rb_root *root)
|
||||
{
|
||||
if (parent) {
|
||||
if (parent->rb_left == old)
|
||||
parent->rb_left = new;
|
||||
else
|
||||
parent->rb_right = new;
|
||||
} else
|
||||
root->rb_node = new;
|
||||
static inline void __rb_change_child(struct rb_node *old, struct rb_node *new,
|
||||
struct rb_node *parent,
|
||||
struct rb_root *root) {
|
||||
if (parent) {
|
||||
if (parent->rb_left == old) {
|
||||
parent->rb_left = new;
|
||||
} else {
|
||||
parent->rb_right = new;
|
||||
}
|
||||
} else {
|
||||
root->rb_node = new;
|
||||
}
|
||||
}
|
||||
|
||||
extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root,
|
||||
void (*augment_rotate)(struct rb_node *old, struct rb_node *new));
|
||||
void (*augment_rotate)(struct rb_node *old,
|
||||
struct rb_node *new));
|
||||
|
||||
static inline struct rb_node *
|
||||
__rb_erase_augmented(struct rb_node *node, struct rb_root *root,
|
||||
const struct rb_augment_callbacks *augment)
|
||||
{
|
||||
struct rb_node *child = node->rb_right, *tmp = node->rb_left;
|
||||
struct rb_node *parent, *rebalance;
|
||||
unsigned long pc;
|
||||
static inline struct rb_node *__rb_erase_augmented(
|
||||
struct rb_node *node, struct rb_root *root,
|
||||
const struct rb_augment_callbacks *augment) {
|
||||
struct rb_node *child = node->rb_right, *tmp = node->rb_left;
|
||||
struct rb_node *parent, *rebalance;
|
||||
unsigned long pc;
|
||||
|
||||
if (!tmp) {
|
||||
/*
|
||||
* Case 1: node to erase has no more than 1 child (easy!)
|
||||
*
|
||||
* Note that if there is one child it must be red due to 5)
|
||||
* and node must be black due to 4). We adjust colors locally
|
||||
* so as to bypass __rb_erase_color() later on.
|
||||
*/
|
||||
pc = node->__rb_parent_color;
|
||||
parent = __rb_parent(pc);
|
||||
__rb_change_child(node, child, parent, root);
|
||||
if (child) {
|
||||
child->__rb_parent_color = pc;
|
||||
rebalance = NULL;
|
||||
} else
|
||||
rebalance = __rb_is_black(pc) ? parent : NULL;
|
||||
tmp = parent;
|
||||
} else if (!child) {
|
||||
/* Still case 1, but this time the child is node->rb_left */
|
||||
tmp->__rb_parent_color = pc = node->__rb_parent_color;
|
||||
parent = __rb_parent(pc);
|
||||
__rb_change_child(node, tmp, parent, root);
|
||||
rebalance = NULL;
|
||||
tmp = parent;
|
||||
} else {
|
||||
struct rb_node *successor = child, *child2;
|
||||
tmp = child->rb_left;
|
||||
if (!tmp) {
|
||||
/*
|
||||
* Case 2: node's successor is its right child
|
||||
*
|
||||
* (n) (s)
|
||||
* / \ / \
|
||||
* (x) (s) -> (x) (c)
|
||||
* \
|
||||
* (c)
|
||||
*/
|
||||
parent = successor;
|
||||
child2 = successor->rb_right;
|
||||
augment->copy(node, successor);
|
||||
} else {
|
||||
/*
|
||||
* Case 3: node's successor is leftmost under
|
||||
* node's right child subtree
|
||||
*
|
||||
* (n) (s)
|
||||
* / \ / \
|
||||
* (x) (y) -> (x) (y)
|
||||
* / /
|
||||
* (p) (p)
|
||||
* / /
|
||||
* (s) (c)
|
||||
* \
|
||||
* (c)
|
||||
*/
|
||||
do {
|
||||
parent = successor;
|
||||
successor = tmp;
|
||||
tmp = tmp->rb_left;
|
||||
} while (tmp);
|
||||
parent->rb_left = child2 = successor->rb_right;
|
||||
successor->rb_right = child;
|
||||
rb_set_parent(child, successor);
|
||||
augment->copy(node, successor);
|
||||
augment->propagate(parent, successor);
|
||||
}
|
||||
if (!tmp) {
|
||||
/*
|
||||
* Case 1: node to erase has no more than 1 child (easy!)
|
||||
*
|
||||
* Note that if there is one child it must be red due to 5)
|
||||
* and node must be black due to 4). We adjust colors locally
|
||||
* so as to bypass __rb_erase_color() later on.
|
||||
*/
|
||||
pc = node->__rb_parent_color;
|
||||
parent = __rb_parent(pc);
|
||||
__rb_change_child(node, child, parent, root);
|
||||
if (child) {
|
||||
child->__rb_parent_color = pc;
|
||||
rebalance = NULL;
|
||||
} else
|
||||
rebalance = __rb_is_black(pc) ? parent : NULL;
|
||||
tmp = parent;
|
||||
} else if (!child) {
|
||||
/* Still case 1, but this time the child is node->rb_left */
|
||||
tmp->__rb_parent_color = pc = node->__rb_parent_color;
|
||||
parent = __rb_parent(pc);
|
||||
__rb_change_child(node, tmp, parent, root);
|
||||
rebalance = NULL;
|
||||
tmp = parent;
|
||||
} else {
|
||||
struct rb_node *successor = child, *child2;
|
||||
tmp = child->rb_left;
|
||||
if (!tmp) {
|
||||
/*
|
||||
* Case 2: node's successor is its right child
|
||||
*
|
||||
* (n) (s)
|
||||
* / \ / \
|
||||
* (x) (s) -> (x) (c)
|
||||
* \
|
||||
* (c)
|
||||
*/
|
||||
parent = successor;
|
||||
child2 = successor->rb_right;
|
||||
augment->copy(node, successor);
|
||||
} else {
|
||||
/*
|
||||
* Case 3: node's successor is leftmost under
|
||||
* node's right child subtree
|
||||
*
|
||||
* (n) (s)
|
||||
* / \ / \
|
||||
* (x) (y) -> (x) (y)
|
||||
* / /
|
||||
* (p) (p)
|
||||
* / /
|
||||
* (s) (c)
|
||||
* \
|
||||
* (c)
|
||||
*/
|
||||
do {
|
||||
parent = successor;
|
||||
successor = tmp;
|
||||
tmp = tmp->rb_left;
|
||||
} while (tmp);
|
||||
parent->rb_left = child2 = successor->rb_right;
|
||||
successor->rb_right = child;
|
||||
rb_set_parent(child, successor);
|
||||
augment->copy(node, successor);
|
||||
augment->propagate(parent, successor);
|
||||
}
|
||||
|
||||
successor->rb_left = tmp = node->rb_left;
|
||||
rb_set_parent(tmp, successor);
|
||||
successor->rb_left = tmp = node->rb_left;
|
||||
rb_set_parent(tmp, successor);
|
||||
|
||||
pc = node->__rb_parent_color;
|
||||
tmp = __rb_parent(pc);
|
||||
__rb_change_child(node, successor, tmp, root);
|
||||
if (child2) {
|
||||
successor->__rb_parent_color = pc;
|
||||
rb_set_parent_color(child2, parent, RB_BLACK);
|
||||
rebalance = NULL;
|
||||
} else {
|
||||
unsigned long pc2 = successor->__rb_parent_color;
|
||||
successor->__rb_parent_color = pc;
|
||||
rebalance = __rb_is_black(pc2) ? parent : NULL;
|
||||
}
|
||||
tmp = successor;
|
||||
}
|
||||
pc = node->__rb_parent_color;
|
||||
tmp = __rb_parent(pc);
|
||||
__rb_change_child(node, successor, tmp, root);
|
||||
if (child2) {
|
||||
successor->__rb_parent_color = pc;
|
||||
rb_set_parent_color(child2, parent, RB_BLACK);
|
||||
rebalance = NULL;
|
||||
} else {
|
||||
unsigned long pc2 = successor->__rb_parent_color;
|
||||
successor->__rb_parent_color = pc;
|
||||
rebalance = __rb_is_black(pc2) ? parent : NULL;
|
||||
}
|
||||
tmp = successor;
|
||||
}
|
||||
|
||||
augment->propagate(tmp, NULL);
|
||||
return rebalance;
|
||||
augment->propagate(tmp, NULL);
|
||||
return rebalance;
|
||||
}
|
||||
|
||||
static inline void
|
||||
rb_erase_augmented(struct rb_node *node, struct rb_root *root,
|
||||
const struct rb_augment_callbacks *augment)
|
||||
{
|
||||
struct rb_node *rebalance = __rb_erase_augmented(node, root, augment);
|
||||
if (rebalance)
|
||||
__rb_erase_color(rebalance, root, augment->rotate);
|
||||
static inline void rb_erase_augmented(
|
||||
struct rb_node *node, struct rb_root *root,
|
||||
const struct rb_augment_callbacks *augment) {
|
||||
struct rb_node *rebalance = __rb_erase_augmented(node, root, augment);
|
||||
if (rebalance) { __rb_erase_color(rebalance, root, augment->rotate); }
|
||||
}
|
||||
|
||||
#endif /* _LINUX_RBTREE_AUGMENTED_H */
|
||||
#endif /* _LINUX_RBTREE_AUGMENTED_H */
|
||||
|
@ -52,25 +52,26 @@ void __libafl_targets_cmplog_instructions(uintptr_t k, uint8_t shape, uint64_t a
|
||||
// to avoid to call it on .text addresses
|
||||
static long area_is_valid(void *ptr, size_t len) {
|
||||
|
||||
if (!ptr || __asan_region_is_poisoned(ptr, len)) return 0;
|
||||
if (!ptr || __asan_region_is_poisoned(ptr, len)) {return 0;}
|
||||
|
||||
long valid_len;
|
||||
|
||||
#if defined(_WIN32)
|
||||
if (IsBadReadPtr(ptr, len)) return 0;
|
||||
if (IsBadReadPtr(ptr, len)) {return 0;}
|
||||
valid_len = (long)len;
|
||||
#elif defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
|
||||
if (!dymmy_initialized) {
|
||||
if ((dummy_fd[1] = open("/dev/null", O_WRONLY)) < 0) {
|
||||
if (pipe(dummy_fd) < 0)
|
||||
if (pipe(dummy_fd) < 0) {
|
||||
dummy_fd[1] = 1;
|
||||
}
|
||||
}
|
||||
dymmy_initialized = 1;
|
||||
}
|
||||
|
||||
valid_len = syscall(SYS_write, dummy_fd[1], ptr, len);
|
||||
|
||||
if (valid_len <= 0 || valid_len > (long)len) return 0;
|
||||
if (valid_len <= 0 || valid_len > (long)len) {return 0;}
|
||||
#endif
|
||||
|
||||
// even if the write succeed this can be a false positive if we cross
|
||||
@ -98,12 +99,13 @@ static long area_is_valid(void *ptr, size_t len) {
|
||||
|
||||
void __libafl_targets_cmplog_routines(uintptr_t k, uint8_t *ptr1, uint8_t *ptr2) {
|
||||
|
||||
if (!libafl_cmplog_enabled) return;
|
||||
if (!libafl_cmplog_enabled) { return; }
|
||||
|
||||
int l1, l2;
|
||||
if ((l1 = area_is_valid(ptr1, CMPLOG_RTN_LEN)) <= 0 ||
|
||||
(l2 = area_is_valid(ptr2, CMPLOG_RTN_LEN)) <= 0)
|
||||
(l2 = area_is_valid(ptr2, CMPLOG_RTN_LEN)) <= 0) {
|
||||
return;
|
||||
}
|
||||
int len = MIN(l1, l2);
|
||||
|
||||
uint32_t hits;
|
||||
@ -115,8 +117,9 @@ void __libafl_targets_cmplog_routines(uintptr_t k, uint8_t *ptr1, uint8_t *ptr2)
|
||||
hits = 0;
|
||||
} else {
|
||||
hits = libafl_cmplog_map_ptr->headers[k].hits++;
|
||||
if (libafl_cmplog_map_ptr->headers[k].shape < len)
|
||||
if (libafl_cmplog_map_ptr->headers[k].shape < len) {
|
||||
libafl_cmplog_map_ptr->headers[k].shape = len;
|
||||
}
|
||||
}
|
||||
|
||||
hits &= CMPLOG_MAP_RTN_H - 1;
|
||||
@ -154,8 +157,8 @@ static uint8_t *get_gcc_stdstring(uint8_t *string) {
|
||||
// IcEEE7compareEmmPKcm
|
||||
static uint8_t *get_llvm_stdstring(uint8_t *string) {
|
||||
|
||||
// length is in: if ((string[0] & 1) == 0) uint8_t len = (string[0] >> 1);
|
||||
// or: if (string[0] & 1) uint32_t *len = (uint32_t *) (string + 8);
|
||||
// length is in: if ((string[0] & 1) == 0) {uint8_t len = (string[0] >> 1);}
|
||||
// or: if (string[0] & 1) {uint32_t *len = (uint32_t *) (string + 8);}
|
||||
|
||||
if (string[0] & 1) { // in memory
|
||||
uint8_t **ptr = (uint8_t **)(string + 16);
|
||||
@ -168,9 +171,10 @@ static uint8_t *get_llvm_stdstring(uint8_t *string) {
|
||||
|
||||
void __cmplog_rtn_gcc_stdstring_cstring(uint8_t *stdstring, uint8_t *cstring) {
|
||||
|
||||
if (!libafl_cmplog_enabled) return;
|
||||
if (area_is_valid(stdstring, 32) <= 0)
|
||||
if (!libafl_cmplog_enabled) {return;}
|
||||
if (area_is_valid(stdstring, 32) <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
__cmplog_rtn_hook(get_gcc_stdstring(stdstring), cstring);
|
||||
|
||||
@ -178,9 +182,10 @@ void __cmplog_rtn_gcc_stdstring_cstring(uint8_t *stdstring, uint8_t *cstring) {
|
||||
|
||||
void __cmplog_rtn_gcc_stdstring_stdstring(uint8_t *stdstring1, uint8_t *stdstring2) {
|
||||
|
||||
if (!libafl_cmplog_enabled) return;
|
||||
if (area_is_valid(stdstring1, 32) <= 0 || area_is_valid(stdstring2, 32) <= 0)
|
||||
if (!libafl_cmplog_enabled) {return;}
|
||||
if (area_is_valid(stdstring1, 32) <= 0 || area_is_valid(stdstring2, 32) <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
__cmplog_rtn_hook(get_gcc_stdstring(stdstring1),
|
||||
get_gcc_stdstring(stdstring2));
|
||||
@ -189,9 +194,10 @@ void __cmplog_rtn_gcc_stdstring_stdstring(uint8_t *stdstring1, uint8_t *stdstrin
|
||||
|
||||
void __cmplog_rtn_llvm_stdstring_cstring(uint8_t *stdstring, uint8_t *cstring) {
|
||||
|
||||
if (!libafl_cmplog_enabled) return;
|
||||
if (area_is_valid(stdstring, 32) <= 0)
|
||||
if (!libafl_cmplog_enabled) {return;}
|
||||
if (area_is_valid(stdstring, 32) <= 0){
|
||||
return;
|
||||
}
|
||||
|
||||
__cmplog_rtn_hook(get_llvm_stdstring(stdstring), cstring);
|
||||
|
||||
@ -199,9 +205,10 @@ void __cmplog_rtn_llvm_stdstring_cstring(uint8_t *stdstring, uint8_t *cstring) {
|
||||
|
||||
void __cmplog_rtn_llvm_stdstring_stdstring(uint8_t *stdstring1, uint8_t *stdstring2) {
|
||||
|
||||
if (!libafl_cmplog_enabled) return;
|
||||
if (area_is_valid(stdstring1, 32) <= 0 || area_is_valid(stdstring2, 32) <= 0)
|
||||
if (!libafl_cmplog_enabled) {return;}
|
||||
if (area_is_valid(stdstring1, 32) <= 0 || area_is_valid(stdstring2, 32) <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
__cmplog_rtn_hook(get_llvm_stdstring(stdstring1),
|
||||
get_llvm_stdstring(stdstring2));
|
||||
|
@ -4,56 +4,59 @@
|
||||
#include "common.h"
|
||||
|
||||
#ifndef CMPLOG_MAP_W
|
||||
#define CMPLOG_MAP_W 65536
|
||||
#define CMPLOG_MAP_W 65536
|
||||
#endif
|
||||
#ifndef CMPLOG_MAP_H
|
||||
#define CMPLOG_MAP_H 32
|
||||
#define CMPLOG_MAP_H 32
|
||||
#endif
|
||||
|
||||
#define CMPLOG_RTN_LEN 32
|
||||
|
||||
#define CMPLOG_MAP_RTN_H ((CMPLOG_MAP_H * sizeof(CmpLogInstruction)) / sizeof(CmpLogRoutine))
|
||||
#define CMPLOG_MAP_RTN_H \
|
||||
((CMPLOG_MAP_H * sizeof(CmpLogInstruction)) / sizeof(CmpLogRoutine))
|
||||
|
||||
#define CMPLOG_KIND_INS 0
|
||||
#define CMPLOG_KIND_RTN 1
|
||||
|
||||
typedef struct CmpLogHeader {
|
||||
uint16_t hits;
|
||||
uint8_t shape;
|
||||
uint8_t kind;
|
||||
uint16_t hits;
|
||||
uint8_t shape;
|
||||
uint8_t kind;
|
||||
} CmpLogHeader;
|
||||
|
||||
typedef struct CmpLogInstruction {
|
||||
uint64_t v0;
|
||||
uint64_t v1;
|
||||
uint64_t v0;
|
||||
uint64_t v1;
|
||||
} CmpLogInstruction;
|
||||
|
||||
typedef struct CmpLogRoutine {
|
||||
uint8_t v0[CMPLOG_RTN_LEN];
|
||||
uint8_t v1[CMPLOG_RTN_LEN];
|
||||
uint8_t v0[CMPLOG_RTN_LEN];
|
||||
uint8_t v1[CMPLOG_RTN_LEN];
|
||||
} CmpLogRoutine;
|
||||
|
||||
typedef struct CmpLogMap {
|
||||
CmpLogHeader headers[CMPLOG_MAP_W];
|
||||
union {
|
||||
CmpLogInstruction operands[CMPLOG_MAP_W][CMPLOG_MAP_H];
|
||||
CmpLogRoutine routines[CMPLOG_MAP_W][CMPLOG_MAP_RTN_H];
|
||||
CmpLogInstruction operands[CMPLOG_MAP_W][CMPLOG_MAP_H];
|
||||
CmpLogRoutine routines[CMPLOG_MAP_W][CMPLOG_MAP_RTN_H];
|
||||
} vals;
|
||||
} CmpLogMap;
|
||||
|
||||
extern CmpLogMap libafl_cmplog_map;
|
||||
extern CmpLogMap* libafl_cmplog_map_ptr;
|
||||
extern CmpLogMap libafl_cmplog_map;
|
||||
extern CmpLogMap *libafl_cmplog_map_ptr;
|
||||
|
||||
extern uint8_t libafl_cmplog_enabled;
|
||||
|
||||
void __libafl_targets_cmplog_instructions(uintptr_t k, uint8_t shape, uint64_t arg1, uint64_t arg2);
|
||||
void __libafl_targets_cmplog_instructions(uintptr_t k, uint8_t shape,
|
||||
uint64_t arg1, uint64_t arg2);
|
||||
|
||||
void __libafl_targets_cmplog_routines(uintptr_t k, uint8_t *ptr1, uint8_t *ptr2);
|
||||
void __libafl_targets_cmplog_routines(uintptr_t k, uint8_t *ptr1,
|
||||
uint8_t *ptr2);
|
||||
|
||||
static inline void __libafl_targets_cmplog(uintptr_t k, uint8_t shape, uint64_t arg1, uint64_t arg2) {
|
||||
static inline void __libafl_targets_cmplog(uintptr_t k, uint8_t shape,
|
||||
uint64_t arg1, uint64_t arg2) {
|
||||
if (!libafl_cmplog_enabled) { return; }
|
||||
|
||||
if (!libafl_cmplog_enabled) return;
|
||||
|
||||
uint16_t hits;
|
||||
if (libafl_cmplog_map_ptr->headers[k].kind != CMPLOG_KIND_INS) {
|
||||
libafl_cmplog_map_ptr->headers[k].kind = CMPLOG_KIND_INS;
|
||||
@ -70,7 +73,6 @@ static inline void __libafl_targets_cmplog(uintptr_t k, uint8_t shape, uint64_t
|
||||
hits &= CMPLOG_MAP_H - 1;
|
||||
libafl_cmplog_map_ptr->vals.operands[k][hits].v0 = arg1;
|
||||
libafl_cmplog_map_ptr->vals.operands[k][hits].v1 = arg2;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -6,21 +6,20 @@
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
#define STATIC_ASSERT(pred) switch(0){case 0:case pred:;}
|
||||
#define STATIC_ASSERT(pred) \
|
||||
switch (0) { \
|
||||
case 0: \
|
||||
case pred:; \
|
||||
}
|
||||
|
||||
// From https://stackoverflow.com/a/18298965
|
||||
#if __STDC_VERSION__ >= 201112 && !defined __STDC_NO_THREADS__
|
||||
#define THREAD_LOCAL _Thread_local
|
||||
#elif defined _WIN32 && ( \
|
||||
defined _MSC_VER || \
|
||||
defined __ICL || \
|
||||
defined __DMC__ || \
|
||||
defined __BORLANDC__ )
|
||||
#define THREAD_LOCAL __declspec(thread)
|
||||
#elif defined _WIN32 && (defined _MSC_VER || defined __ICL || \
|
||||
defined __DMC__ || defined __BORLANDC__)
|
||||
#define THREAD_LOCAL __declspec(thread)
|
||||
/* note that ICC (linux) and Clang are covered by __GNUC__ */
|
||||
#elif defined __GNUC__ || \
|
||||
defined __SUNPRO_C || \
|
||||
defined __xlC__
|
||||
#elif defined __GNUC__ || defined __SUNPRO_C || defined __xlC__
|
||||
#define THREAD_LOCAL __thread
|
||||
#endif
|
||||
|
||||
@ -40,119 +39,116 @@
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define RETADDR (uintptr_t)_ReturnAddress()
|
||||
#define RETADDR (uintptr_t) _ReturnAddress()
|
||||
#define EXPORT_FN __declspec(dllexport)
|
||||
#else
|
||||
#define RETADDR (uintptr_t)__builtin_return_address(0)
|
||||
#define RETADDR (uintptr_t) __builtin_return_address(0)
|
||||
#define EXPORT_FN
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define MAX(a, b) \
|
||||
({ \
|
||||
\
|
||||
__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a > _b ? _a : _b; \
|
||||
\
|
||||
})
|
||||
#define MIN(a, b) \
|
||||
({ \
|
||||
\
|
||||
__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a < _b ? _a : _b; \
|
||||
\
|
||||
})
|
||||
#define MEMCPY __builtin_memcpy
|
||||
#else
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define MEMCPY memcpy
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
// From Libfuzzer
|
||||
// Intermediate macro to ensure the parameter is expanded before stringified.
|
||||
#define STRINGIFY_(A) #A
|
||||
#define STRINGIFY(A) STRINGIFY_(A)
|
||||
// From Libfuzzer
|
||||
// Intermediate macro to ensure the parameter is expanded before stringified.
|
||||
#define STRINGIFY_(A) #A
|
||||
#define STRINGIFY(A) STRINGIFY_(A)
|
||||
|
||||
#if _MSC_VER
|
||||
// Copied from compiler-rt/lib/sanitizer_common/sanitizer_win_defs.h
|
||||
#if defined(_M_IX86) || defined(__i386__)
|
||||
#define WIN_SYM_PREFIX "_"
|
||||
#else
|
||||
#define WIN_SYM_PREFIX
|
||||
#endif
|
||||
#if _MSC_VER
|
||||
// Copied from compiler-rt/lib/sanitizer_common/sanitizer_win_defs.h
|
||||
#if defined(_M_IX86) || defined(__i386__)
|
||||
#define WIN_SYM_PREFIX "_"
|
||||
#else
|
||||
#define WIN_SYM_PREFIX
|
||||
#endif
|
||||
|
||||
// Declare external functions as having alternativenames, so that we can
|
||||
// determine if they are not defined.
|
||||
#define EXTERNAL_FUNC(Name, Default) \
|
||||
__pragma(comment(linker, "/alternatename:" WIN_SYM_PREFIX STRINGIFY( \
|
||||
Name) "=" WIN_SYM_PREFIX STRINGIFY(Default)))
|
||||
// Declare external functions as having alternativenames, so that we can
|
||||
// determine if they are not defined.
|
||||
#define EXTERNAL_FUNC(Name, Default) \
|
||||
__pragma( \
|
||||
comment(linker, "/alternatename:" WIN_SYM_PREFIX STRINGIFY( \
|
||||
Name) "=" WIN_SYM_PREFIX STRINGIFY(Default)))
|
||||
|
||||
#define CHECK_WEAK_FN(Name) ((void*)Name != (void*)&Name##Def)
|
||||
#define CHECK_WEAK_FN(Name) ((void *)Name != (void *)&Name##Def)
|
||||
|
||||
#define EXT_FUNC_IMPL(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
|
||||
RETURN_TYPE NAME##Def FUNC_SIG; \
|
||||
EXTERNAL_FUNC(NAME, NAME##Def) RETURN_TYPE NAME FUNC_SIG; \
|
||||
RETURN_TYPE NAME##Def FUNC_SIG \
|
||||
#define EXT_FUNC_IMPL(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
|
||||
RETURN_TYPE NAME##Def FUNC_SIG; \
|
||||
EXTERNAL_FUNC(NAME, NAME##Def) RETURN_TYPE NAME FUNC_SIG; \
|
||||
RETURN_TYPE NAME##Def FUNC_SIG
|
||||
|
||||
#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
|
||||
RETURN_TYPE (*NAME##Def) FUNC_SIG = NULL; \
|
||||
EXTERNAL_FUNC(NAME, NAME##Def) RETURN_TYPE NAME FUNC_SIG
|
||||
#else
|
||||
// Declare external functions as weak to allow them to default to a specified
|
||||
// function if not defined explicitly. We must use weak symbols because clang's
|
||||
// support for alternatename is not 100%, see
|
||||
// https://bugs.llvm.org/show_bug.cgi?id=40218 for more details.
|
||||
#define EXTERNAL_FUNC(Name, Default) \
|
||||
__attribute__((weak, alias(STRINGIFY(Default))))
|
||||
#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
|
||||
RETURN_TYPE(*NAME##Def) FUNC_SIG = NULL; \
|
||||
EXTERNAL_FUNC(NAME, NAME##Def) RETURN_TYPE NAME FUNC_SIG
|
||||
#else
|
||||
// Declare external functions as weak to allow them to default to a
|
||||
// specified function if not defined explicitly. We must use weak symbols
|
||||
// because clang's support for alternatename is not 100%, see
|
||||
// https://bugs.llvm.org/show_bug.cgi?id=40218 for more details.
|
||||
#define EXTERNAL_FUNC(Name, Default) \
|
||||
__attribute__((weak, alias(STRINGIFY(Default))))
|
||||
|
||||
#define CHECK_WEAK_FN(Name) (Name != NULL)
|
||||
#define CHECK_WEAK_FN(Name) (Name != NULL)
|
||||
|
||||
#define EXT_FUNC_IMPL(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
|
||||
EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN)
|
||||
#define EXT_FUNC_IMPL(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
|
||||
EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN)
|
||||
|
||||
#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
|
||||
RETURN_TYPE (*NAME##Def) FUNC_SIG = NULL; \
|
||||
EXTERNAL_FUNC(NAME, NAME##Def) RETURN_TYPE NAME FUNC_SIG
|
||||
#endif // _MSC_VER
|
||||
#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
|
||||
RETURN_TYPE(*NAME##Def) FUNC_SIG = NULL; \
|
||||
EXTERNAL_FUNC(NAME, NAME##Def) RETURN_TYPE NAME FUNC_SIG
|
||||
#endif // _MSC_VER
|
||||
|
||||
#else
|
||||
|
||||
#if defined(__APPLE__)
|
||||
// On Apple, weak_import and weak attrs behave differently to linux.
|
||||
#if defined(__APPLE__)
|
||||
// On Apple, weak_import and weak attrs behave differently to linux.
|
||||
|
||||
#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
|
||||
__attribute__((weak, visibility("default"))) RETURN_TYPE NAME FUNC_SIG { \
|
||||
return (RETURN_TYPE) 0; \
|
||||
}
|
||||
#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
|
||||
__attribute__((weak, visibility("default"))) RETURN_TYPE NAME FUNC_SIG { \
|
||||
return (RETURN_TYPE)0; \
|
||||
}
|
||||
|
||||
#define EXT_FUNC_IMPL(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
|
||||
__attribute__((weak, visibility("default"))) RETURN_TYPE NAME FUNC_SIG
|
||||
#define EXT_FUNC_IMPL(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
|
||||
__attribute__((weak, visibility("default"))) RETURN_TYPE NAME FUNC_SIG
|
||||
|
||||
// Weakly defined globals
|
||||
#define EXT_VAR(NAME, TYPE) \
|
||||
TYPE __attribute__((weak, visibility("default"))) NAME
|
||||
// Weakly defined globals
|
||||
#define EXT_VAR(NAME, TYPE) \
|
||||
TYPE __attribute__((weak, visibility("default"))) NAME
|
||||
|
||||
#else
|
||||
#else
|
||||
|
||||
#define EXT_FUNC_IMPL(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
|
||||
EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN)
|
||||
#define EXT_FUNC_IMPL(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
|
||||
EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN)
|
||||
|
||||
// Declare these symbols as weak to allow them to be optionally defined.
|
||||
#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
|
||||
__attribute__((weak, visibility("default"))) RETURN_TYPE NAME FUNC_SIG
|
||||
// Declare these symbols as weak to allow them to be optionally defined.
|
||||
#define EXT_FUNC(NAME, RETURN_TYPE, FUNC_SIG, WARN) \
|
||||
__attribute__((weak, visibility("default"))) RETURN_TYPE NAME FUNC_SIG
|
||||
|
||||
// Weakly defined globals
|
||||
#define EXT_VAR(NAME, TYPE) \
|
||||
TYPE __attribute__((weak, visibility("default"))) NAME
|
||||
|
||||
#endif
|
||||
|
||||
#define CHECK_WEAK_FN(Name) (Name != NULL)
|
||||
#endif // _WIN32
|
||||
// Weakly defined globals
|
||||
#define EXT_VAR(NAME, TYPE) \
|
||||
TYPE __attribute__((weak, visibility("default"))) NAME
|
||||
|
||||
#endif
|
||||
|
||||
#define CHECK_WEAK_FN(Name) (Name != NULL)
|
||||
#endif // _WIN32
|
||||
|
||||
#endif
|
||||
|
@ -76,7 +76,7 @@ void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) {
|
||||
|
||||
uintptr_t rt = RETADDR;
|
||||
|
||||
// if (!cases[1]) return;
|
||||
// if (!cases[1]) {return;}
|
||||
|
||||
for (uint64_t i = 0; i < cases[0]; i++) {
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "common.h"
|
||||
|
||||
#ifndef CMP_MAP_SIZE
|
||||
#define CMP_MAP_SIZE 65536
|
||||
#define CMP_MAP_SIZE 65536
|
||||
#endif
|
||||
|
||||
extern uint8_t libafl_cmp_map[CMP_MAP_SIZE];
|
||||
@ -15,28 +15,28 @@ extern uint8_t libafl_cmp_map[CMP_MAP_SIZE];
|
||||
#define __builtin_popcountll __popcnt64
|
||||
#endif
|
||||
|
||||
static void __libafl_targets_value_profile1(uintptr_t k, uint8_t arg1, uint8_t arg2) {
|
||||
|
||||
libafl_cmp_map[k] = MAX(libafl_cmp_map[k], (__builtin_popcount(~(arg1 ^ arg2))));
|
||||
|
||||
static void __libafl_targets_value_profile1(uintptr_t k, uint8_t arg1,
|
||||
uint8_t arg2) {
|
||||
libafl_cmp_map[k] =
|
||||
MAX(libafl_cmp_map[k], (__builtin_popcount(~(arg1 ^ arg2))));
|
||||
}
|
||||
|
||||
static void __libafl_targets_value_profile2(uintptr_t k, uint16_t arg1, uint16_t arg2) {
|
||||
|
||||
libafl_cmp_map[k] = MAX(libafl_cmp_map[k], (__builtin_popcount(~(arg1 ^ arg2))));
|
||||
|
||||
static void __libafl_targets_value_profile2(uintptr_t k, uint16_t arg1,
|
||||
uint16_t arg2) {
|
||||
libafl_cmp_map[k] =
|
||||
MAX(libafl_cmp_map[k], (__builtin_popcount(~(arg1 ^ arg2))));
|
||||
}
|
||||
|
||||
static void __libafl_targets_value_profile4(uintptr_t k, uint32_t arg1, uint32_t arg2) {
|
||||
|
||||
libafl_cmp_map[k] = MAX(libafl_cmp_map[k], (__builtin_popcount(~(arg1 ^ arg2))));
|
||||
|
||||
static void __libafl_targets_value_profile4(uintptr_t k, uint32_t arg1,
|
||||
uint32_t arg2) {
|
||||
libafl_cmp_map[k] =
|
||||
MAX(libafl_cmp_map[k], (__builtin_popcount(~(arg1 ^ arg2))));
|
||||
}
|
||||
|
||||
static void __libafl_targets_value_profile8(uintptr_t k, uint64_t arg1, uint64_t arg2) {
|
||||
|
||||
libafl_cmp_map[k] = MAX(libafl_cmp_map[k], (__builtin_popcountll(~(arg1 ^ arg2))));
|
||||
|
||||
static void __libafl_targets_value_profile8(uintptr_t k, uint64_t arg1,
|
||||
uint64_t arg2) {
|
||||
libafl_cmp_map[k] =
|
||||
MAX(libafl_cmp_map[k], (__builtin_popcountll(~(arg1 ^ arg2))));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -5,7 +5,7 @@
|
||||
test "$1" = "-h" -o "$1" = "-hh" && {
|
||||
echo 'afl-persistent-config'
|
||||
echo
|
||||
echo $0
|
||||
echo "$0"
|
||||
echo
|
||||
echo afl-persistent-config has no command line options
|
||||
echo
|
||||
@ -32,7 +32,7 @@ if [[ "$ANSWER" != "YES" ]]; then
|
||||
fi
|
||||
|
||||
echo
|
||||
PLATFORM=`uname -s`
|
||||
PLATFORM=$(uname -s)
|
||||
|
||||
# check that we're on Mac
|
||||
if [[ "$PLATFORM" = "Darwin" ]] ; then
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
||||
cd "$SCRIPT_DIR/.."
|
||||
cd "$SCRIPT_DIR/.." || exit 1
|
||||
|
||||
# Clippy checks
|
||||
if [ "$1" != "--no-clean" ]; then
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
||||
cd "$SCRIPT_DIR/.."
|
||||
cd "$SCRIPT_DIR/.." || exit 1
|
||||
|
||||
# TODO: This should be rewritten in rust, a Makefile, or some platform-independent language
|
||||
|
||||
@ -12,10 +12,11 @@ cargo clean
|
||||
fuzzers=$(find ./fuzzers -maxdepth 1 -type d)
|
||||
backtrace_fuzzers=$(find ./fuzzers/backtrace_baby_fuzzers -maxdepth 1 -type d)
|
||||
|
||||
for fuzzer in $(echo $fuzzers $backtrace_fuzzers);
|
||||
# shellcheck disable=SC2116
|
||||
for fuzzer in $(echo "$fuzzers" "$backtrace_fuzzers");
|
||||
do
|
||||
pushd $fuzzer
|
||||
pushd "$fuzzer" || exit 1
|
||||
echo "[*] Running clean for $fuzzer"
|
||||
cargo clean
|
||||
popd
|
||||
popd || exit 1
|
||||
done
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
||||
cd "$SCRIPT_DIR/.."
|
||||
cd "$SCRIPT_DIR/.." || exit 1
|
||||
|
||||
# Clippy checks
|
||||
if [ "$1" != "--no-clean" ]; then
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
||||
cd "$SCRIPT_DIR/.."
|
||||
cd "$SCRIPT_DIR/.." || exit 1
|
||||
|
||||
# TODO: This should be rewritten in rust, a Makefile, or some platform-independent language
|
||||
|
||||
@ -9,13 +9,20 @@ echo "Welcome to the happy fmt script. :)"
|
||||
echo "[*] Running fmt for the main crates"
|
||||
cargo fmt
|
||||
|
||||
echo "[*] Formatting C(pp) files"
|
||||
# shellcheck disable=SC2046
|
||||
clang-format-13 -i --style=file $(find . -type f \( -name '*.cpp' -o -iname '*.hpp' -o -name '*.cc' -o -name '*.cxx' -o -name '*.cc' -o -name '*.h' \) | grep -v '/target/' | grep -v 'libpng-1\.6\.37' | grep -v 'stb_image\.h' | grep -v 'dlmalloc\.c')
|
||||
|
||||
|
||||
|
||||
fuzzers=$(find ./fuzzers -maxdepth 1 -type d)
|
||||
backtrace_fuzzers=$(find ./fuzzers/backtrace_baby_fuzzers -maxdepth 1 -type d)
|
||||
|
||||
for fuzzer in $(echo $fuzzers $backtrace_fuzzers);
|
||||
# shellcheck disable=SC2116
|
||||
for fuzzer in $(echo "$fuzzers" "$backtrace_fuzzers");
|
||||
do
|
||||
pushd $fuzzer
|
||||
pushd "$fuzzer" || exit 1
|
||||
echo "[*] Running fmt for $fuzzer"
|
||||
cargo fmt --all
|
||||
popd
|
||||
popd || exit 1
|
||||
done
|
||||
|
@ -1,54 +1,54 @@
|
||||
#!/bin/bash
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
||||
cd "$SCRIPT_DIR/.."
|
||||
cd "$SCRIPT_DIR/.." || exit 1
|
||||
|
||||
set -e
|
||||
|
||||
cd libafl_derive
|
||||
cargo publish $@
|
||||
cd ..
|
||||
cargo publish "$@"
|
||||
cd .. || exit 1
|
||||
|
||||
sleep 20
|
||||
|
||||
cd libafl_cc
|
||||
cargo publish $@
|
||||
cd ..
|
||||
cargo publish "$@"
|
||||
cd .. || exit 1
|
||||
|
||||
sleep 20
|
||||
|
||||
cd libafl
|
||||
cargo publish $@
|
||||
cd ..
|
||||
cargo publish "$@"
|
||||
cd .. || exit 1
|
||||
|
||||
sleep 20
|
||||
|
||||
cd libafl_targets
|
||||
cargo publish $@
|
||||
cd ..
|
||||
cargo publish "$@"
|
||||
cd .. || exit 1
|
||||
|
||||
sleep 20
|
||||
|
||||
cd libafl_frida
|
||||
cargo publish $@
|
||||
cd ..
|
||||
cargo publish "$@"
|
||||
cd .. || exit 1
|
||||
|
||||
sleep 20
|
||||
|
||||
cd libafl_qemu
|
||||
cargo publish $@
|
||||
cd ..
|
||||
cargo publish "$@"
|
||||
cd .. || exit 1
|
||||
|
||||
sleep 20
|
||||
|
||||
cd libafl_sugar
|
||||
cargo publish $@
|
||||
cd ..
|
||||
cargo publish "$@"
|
||||
cd .. || exit 1
|
||||
|
||||
sleep 20
|
||||
|
||||
cd libafl_concolic/symcc_libafl
|
||||
cargo publish $@
|
||||
cd ../..
|
||||
cargo publish "$@"
|
||||
cd ../.. || exit 1
|
||||
|
||||
sleep 20
|
||||
|
||||
@ -60,5 +60,5 @@ if git submodule status | grep "^-">/dev/null ; then \
|
||||
fi
|
||||
|
||||
cd libafl_concolic/symcc_runtime
|
||||
cargo publish $@
|
||||
cd ../..
|
||||
cargo publish "$@"
|
||||
cd ../.. || exit 1
|
||||
|
@ -1,5 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# shellcheck disable=SC2016
|
||||
echo "Warning: this script is not a proper fix to do LLMP fuzzing." \
|
||||
'Instead, run `afl-persistent-config` with SIP disabled.'
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
||||
cd "$SCRIPT_DIR/.."
|
||||
cd "$SCRIPT_DIR/.." || exit 1
|
||||
|
||||
# TODO: This should be rewritten in rust, a Makefile, or some platform-independent language
|
||||
|
||||
@ -25,11 +25,11 @@ done
|
||||
# record time of each fuzzer
|
||||
declare -A time_record || (echo "declare -A not avaliable, please update your bash version to 4";exit 1)
|
||||
|
||||
|
||||
for fuzzer in $(echo $fuzzers $backtrace_fuzzers);
|
||||
# shellcheck disable=SC2116
|
||||
for fuzzer in $(echo "$fuzzers" "$backtrace_fuzzers");
|
||||
do
|
||||
cd $fuzzer
|
||||
start=`date +%s`
|
||||
cd "$fuzzer" || exit 1
|
||||
start=$(date +%s)
|
||||
# Clippy checks
|
||||
if [ "$1" != "--no-fmt" ]; then
|
||||
|
||||
@ -50,15 +50,15 @@ do
|
||||
cargo build || exit 1
|
||||
echo "[+] Done building $fuzzer"
|
||||
fi
|
||||
end=`date +%s`
|
||||
end=$(date +%s)
|
||||
time_record[$fuzzer]=$((end-start))
|
||||
# Save disk space
|
||||
cargo clean
|
||||
cd $libafl
|
||||
cd "$libafl" || exit 1
|
||||
echo ""
|
||||
done
|
||||
|
||||
# print time for each fuzzer
|
||||
for key in ${!time_record[@]}; do
|
||||
echo "dir:"$key" time:"${time_record[$key]};
|
||||
for key in "${!time_record[@]}"; do
|
||||
echo "dir: $key, time: ${time_record[$key]}";
|
||||
done
|
||||
|
Loading…
x
Reference in New Issue
Block a user