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