AFLplusplus/src/afl-fuzz-redqueen.c
van Hauser 7bcd4e2901
push to stable (#973)
* use atomic read-modify-write increment for LLVM CLASSIC

* Change other LLVM modes to atomic increments

* sync (#886)

* Create FUNDING.yml

* Update FUNDING.yml

* moved custom_mutator examples

* unicorn speedtest makefile cleanup

* fixed example location

* fix qdbi

* update util readme

* work in progress: not working correctly yet

* Frida persistent (#880)

* Added x64 support for persistent mode (function call only), in-memory teest cases and complog

* Review changes, fix NeverZero and code to parse the .text section of the main executable. Excluded ranges TBC

* Various minor fixes and finished support for AFL_INST_LIBS

* Review changes

Co-authored-by: Your Name <you@example.com>

* nits

* fix frida mode

* Integer overflow/underflow fixes in libdislocator (#889)

* libdislocator: fixing integer overflow in 'max_mem' variable and setting 'max_mem' type to 'size_t'

* libdislocator: fixing potential integer underflow in 'total_mem' variable due to its different values in different threads

* Bumped warnings up to the max and fixed remaining issues (#890)

Co-authored-by: Your Name <you@example.com>

* nits

* frida mode - support non-pie

* nits

* nit

* update grammar mutator

* Fixes for aarch64, OSX and other minor issues (#891)

Co-authored-by: Your Name <you@example.com>

* nits

* nits

* fix PCGUARD, build aflpp_driver with fPIC

* Added representative fuzzbench test and test for libxml (#893)

* Added representative fuzzbench test and test for libxml

* Added support for building FRIDA from source with FRIDA_SOURCE=1

Co-authored-by: Your Name <you@example.com>

* nits

* update changelog

* typos

* still not working

* fixed potential double free in custom trim (#881)

* error handling, freeing mem

* frida: complog -> cmplog

* fix statsd writing

* let aflpp_qemu_driver_hook.so build fail gracefully

* fix stdin trimming

* Support for AFL_ENTRYPOINT (#898)

Co-authored-by: Your Name <you@example.com>

* remove the input file .cur_input at the end of the fuzzing, if AFL_TMPDIR is used

* reverse push (#901)

* Create FUNDING.yml

* Update FUNDING.yml

* disable QEMU static pie

Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>

* clarify that no modifications are required.

* add new test for frida_mode (please review)

* typos

* fix persistent mode (64-bit)

* set ARCH for linux intel 32-bit for frida-gum-devkit

* prepare for 32-bit support (later)

* not on qemu 3 anymore

* unicorn mips fixes

* instrumentation further move to C++11 (#900)

* unicorn fixes

* first working NeverZero implementation

* more unicorn fixes

* Fix memory errors when trim causes testcase growth (#881) (#903)

* Revert "fixed potential double free in custom trim (#881)"

This reverts commit e9d2f72382cab75832721d859c3e731da071435d.

* Revert "fix custom trim for increasing data"

This reverts commit 86a8ef168dda766d2f25f15c15c4d3ecf21d0667.

* Fix memory errors when trim causes testcase growth

Modify trim_case_custom to avoid writing into in_buf because
some custom mutators can cause the testcase to grow rather than
shrink.

Instead of modifying in_buf directly, we write the update out
to the disk when trimming is complete, and then the caller is
responsible for refreshing the in-memory buffer from the file.

This is still a bit sketchy because it does need to modify q->len in
order to notify the upper layers that something changed, and it could
end up telling upper layer code that the q->len is *bigger* than
the buffer (q->testcase_buf) that contains it, which is asking
for trouble down the line somewhere...

* Fix an unlikely situation

Put back some `unlikely()` calls that were in
the e9d2f72382cab75832721d859c3e731da071435d commit that was
reverted.

* add some comments

* typo

* Exit on time (#904)

* Variable AFL_EXIT_ON_TIME description has been added.
Variables AFL_EXIT_ON_TIME and afl_exit_on_time has been added.
afl->exit_on_time variable initialization has been added.
The asignment of a value to the afl->afl_env.afl_exit_on_time variable from
environment variables has been added.
Code to exit on timeout if new path not found has been added.

* Type of afl_exit_on_time variable has been changed.
Variable exit_on_time has been added to the afl_state_t structure.

* Command `export AFL_EXIT_WHEN_DONE=1` has been added.

* Millisecond to second conversion has been added.
Call get_cur_time() has been added.

* Revert to using the saved current time value.

* Useless check has been removed.

* fix new path to custom-mutators

* ensure crashes/README.txt exists

* fix

* Changes to bump FRIDA version and to clone FRIDA repo in to build directory rather than use a submodule as the FRIDA build scripts don't like it (#906)

Co-authored-by: Your Name <you@example.com>

* Fix numeric overflow in cmplog implementation (#907)

Co-authored-by: Your Name <you@example.com>

* testcase fixes for unicorn

* remove merge conflict artifacts

* fix afl-plot

* Changes to remove binaries from frida_mode (#913)

Co-authored-by: Your Name <you@example.com>

* Frida cmplog fail fast (#914)

* Changes to remove binaries from frida_mode

* Changes to make cmplog fail fast

Co-authored-by: Your Name <you@example.com>

* afl-plot: relative time

* arch linux and mac os support for afl-system-config

* typo

* code-format

* update documentation

* github workflow for qemu

* OSX-specific improvements (#912)

* Fix afl-cc to work correctly by default on OSX using xcode

- CLANG_ENV_VAR must be set for afl-as to work
- Use clang mode by default if no specific compiler selected

* Add OSX-specific documentation for configuring shared memory

* Fixes to memory operands for complog (#916)

Co-authored-by: Your Name <you@example.com>

* fix a few cur_time uses

* added bounds check to pivot_inputs (fixes #921)

* additional safety checks for restarts

* restrict afl-showmap in_file size

* fix seed crash disable

* add warning for afl-showmap partial read

* no core dumps

* AFL_PRINT_FILENAMES added

* more documentation for AFL_EXIT_ON_TIME

* Flushing for AFL_PRINT_FILENAMES

* FASAN Support (#918)

* FASAN Support

* Fix handling of Address Sanitizer DSO

* Changes to identification of Address Sanitizer DSO

Co-authored-by: Your Name <you@example.com>

* Support for x86 (#920)

Co-authored-by: Your Name <you@example.com>

* Update frida_mode readme (#925)

* libqasan: use syscalls for read and write

* update readme

* Minor integration tweaks (#926)

Co-authored-by: Your Name <you@example.com>

* merge

* fix afl-fuzz.c frida preload

* cleaned up AFL_PRINT_FILENAMES env

* Changes to have persistent mode exit at the end of the loop (#928)

Co-authored-by: Your Name <you@example.com>

* fix llvm-dict2file

* push to stable (#931) (#932)

* sync (#886)

* Create FUNDING.yml

* Update FUNDING.yml

* moved custom_mutator examples

* unicorn speedtest makefile cleanup

* fixed example location

* fix qdbi

* update util readme

* Frida persistent (#880)

* Added x64 support for persistent mode (function call only), in-memory teest cases and complog

* Review changes, fix NeverZero and code to parse the .text section of the main executable. Excluded ranges TBC

* Various minor fixes and finished support for AFL_INST_LIBS

* Review changes

Co-authored-by: Your Name <you@example.com>

* nits

* fix frida mode

* Integer overflow/underflow fixes in libdislocator (#889)

* libdislocator: fixing integer overflow in 'max_mem' variable and setting 'max_mem' type to 'size_t'

* libdislocator: fixing potential integer underflow in 'total_mem' variable due to its different values in different threads

* Bumped warnings up to the max and fixed remaining issues (#890)

Co-authored-by: Your Name <you@example.com>

* nits

* frida mode - support non-pie

* nits

* nit

* update grammar mutator

* Fixes for aarch64, OSX and other minor issues (#891)

Co-authored-by: Your Name <you@example.com>

* nits

* nits

* fix PCGUARD, build aflpp_driver with fPIC

* Added representative fuzzbench test and test for libxml (#893)

* Added representative fuzzbench test and test for libxml

* Added support for building FRIDA from source with FRIDA_SOURCE=1

Co-authored-by: Your Name <you@example.com>

* nits

* update changelog

* typos

* fixed potential double free in custom trim (#881)

* error handling, freeing mem

* frida: complog -> cmplog

* fix statsd writing

* let aflpp_qemu_driver_hook.so build fail gracefully

* fix stdin trimming

* Support for AFL_ENTRYPOINT (#898)

Co-authored-by: Your Name <you@example.com>

* remove the input file .cur_input at the end of the fuzzing, if AFL_TMPDIR is used

* reverse push (#901)

* Create FUNDING.yml

* Update FUNDING.yml

* disable QEMU static pie

Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>

* clarify that no modifications are required.

* add new test for frida_mode (please review)

* typos

* fix persistent mode (64-bit)

* set ARCH for linux intel 32-bit for frida-gum-devkit

* prepare for 32-bit support (later)

* not on qemu 3 anymore

* unicorn mips fixes

* instrumentation further move to C++11 (#900)

* unicorn fixes

* more unicorn fixes

* Fix memory errors when trim causes testcase growth (#881) (#903)

* Revert "fixed potential double free in custom trim (#881)"

This reverts commit e9d2f72382cab75832721d859c3e731da071435d.

* Revert "fix custom trim for increasing data"

This reverts commit 86a8ef168dda766d2f25f15c15c4d3ecf21d0667.

* Fix memory errors when trim causes testcase growth

Modify trim_case_custom to avoid writing into in_buf because
some custom mutators can cause the testcase to grow rather than
shrink.

Instead of modifying in_buf directly, we write the update out
to the disk when trimming is complete, and then the caller is
responsible for refreshing the in-memory buffer from the file.

This is still a bit sketchy because it does need to modify q->len in
order to notify the upper layers that something changed, and it could
end up telling upper layer code that the q->len is *bigger* than
the buffer (q->testcase_buf) that contains it, which is asking
for trouble down the line somewhere...

* Fix an unlikely situation

Put back some `unlikely()` calls that were in
the e9d2f72382cab75832721d859c3e731da071435d commit that was
reverted.

* typo

* Exit on time (#904)

* Variable AFL_EXIT_ON_TIME description has been added.
Variables AFL_EXIT_ON_TIME and afl_exit_on_time has been added.
afl->exit_on_time variable initialization has been added.
The asignment of a value to the afl->afl_env.afl_exit_on_time variable from
environment variables has been added.
Code to exit on timeout if new path not found has been added.

* Type of afl_exit_on_time variable has been changed.
Variable exit_on_time has been added to the afl_state_t structure.

* Command `export AFL_EXIT_WHEN_DONE=1` has been added.

* Millisecond to second conversion has been added.
Call get_cur_time() has been added.

* Revert to using the saved current time value.

* Useless check has been removed.

* fix new path to custom-mutators

* ensure crashes/README.txt exists

* fix

* Changes to bump FRIDA version and to clone FRIDA repo in to build directory rather than use a submodule as the FRIDA build scripts don't like it (#906)

Co-authored-by: Your Name <you@example.com>

* Fix numeric overflow in cmplog implementation (#907)

Co-authored-by: Your Name <you@example.com>

* testcase fixes for unicorn

* remove merge conflict artifacts

* fix afl-plot

* Changes to remove binaries from frida_mode (#913)

Co-authored-by: Your Name <you@example.com>

* Frida cmplog fail fast (#914)

* Changes to remove binaries from frida_mode

* Changes to make cmplog fail fast

Co-authored-by: Your Name <you@example.com>

* afl-plot: relative time

* arch linux and mac os support for afl-system-config

* typo

* code-format

* update documentation

* github workflow for qemu

* OSX-specific improvements (#912)

* Fix afl-cc to work correctly by default on OSX using xcode

- CLANG_ENV_VAR must be set for afl-as to work
- Use clang mode by default if no specific compiler selected

* Add OSX-specific documentation for configuring shared memory

* Fixes to memory operands for complog (#916)

Co-authored-by: Your Name <you@example.com>

* fix a few cur_time uses

* added bounds check to pivot_inputs (fixes #921)

* additional safety checks for restarts

* restrict afl-showmap in_file size

* fix seed crash disable

* add warning for afl-showmap partial read

* no core dumps

* AFL_PRINT_FILENAMES added

* more documentation for AFL_EXIT_ON_TIME

* Flushing for AFL_PRINT_FILENAMES

* FASAN Support (#918)

* FASAN Support

* Fix handling of Address Sanitizer DSO

* Changes to identification of Address Sanitizer DSO

Co-authored-by: Your Name <you@example.com>

* Support for x86 (#920)

Co-authored-by: Your Name <you@example.com>

* Update frida_mode readme (#925)

* libqasan: use syscalls for read and write

* update readme

* Minor integration tweaks (#926)

Co-authored-by: Your Name <you@example.com>

* merge

* fix afl-fuzz.c frida preload

* cleaned up AFL_PRINT_FILENAMES env

* Changes to have persistent mode exit at the end of the loop (#928)

Co-authored-by: Your Name <you@example.com>

* fix llvm-dict2file

Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: hexcoder <hexcoder-@users.noreply.github.com>
Co-authored-by: hexcoder- <heiko@hexco.de>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>

Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: hexcoder <hexcoder-@users.noreply.github.com>
Co-authored-by: hexcoder- <heiko@hexco.de>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>

* improve error msg

* Added documentation for wine LoadLibrary workaround (#933)

* Fix cmake target compilation command example (#934)

- Fix typo DCMAKE_C_COMPILERC -> DCMAKE_C_COMPILER.
- Add `cd build` after `mkdir build`.

* showmap passes queue items in alphabetical order

* added tmp files to gitignore

* lenient dict parsing, no map size enum for binary fuzzing

* added info about showmap queue directions

* update binary-only doc

* turn off map size detection if skip_bin_check is set

* Typo

* update docs

* update afl-system-config

* Set kill signal before using it in afl-showmap (#935)

* fix afl-cc help output

* add libafl to binary-only doc

* update docs

* less executions on variable paths

* AFL_SKIP_CRASHES is obsolete since 3.0

* add AFL_TRY_AFFINITY

* Typo

* Typo

* Typo/wording

* tweaks

* typos

* fix afl-whatsup help output

* fix afl-plot output

* fix for MacOS

* fix cmpcov doc for qemu

* fix tmpfile removal

* update dockerfile

* Frida (#940)

* Added re2 test

* Added libpcap test

* Fix validation of setting of ADDR_NO_RANDOMIZE

* Added support for printing original and instrumented code

Co-authored-by: Your Name <you@example.com>

* Support for AFL_FRIDA_PERSISTENT_RET (#941)

Co-authored-by: Your Name <you@example.com>

* Changes to add missing exclusion of ranges (#943)

Co-authored-by: Your Name <you@example.com>

* add --afl-noopt to afl-cc

* docs: fix link to README in QuickStartGuide (#946)

* Support writing Stalker stats (#945)

* Support writing Stalker stats

* Fixed string handling in print functions

Co-authored-by: Your Name <you@example.com>

* afl-cmin help fix, aflpp_driver - + @@ support

* fix for afl-showmap

* support new env var AFL_LLVM_THREADSAFE_INST to enable atomic counters.
add new test case for that.

* add documentation for AFL_LLVM_THREADSAFE_INST

* add support for AFL_LLVM_THREADSAFE_INST to other LLVM passes

* add missing include for _exit()

* threadsafe doc fixes, code format

* Wording: "never zero" -> NeverZero

* fix afl_custom_post_process with multiple custom mutators

* fix docs

* debug ck_write

* fixed potential diff by 0

* fixes

* fix classic threadsafe counters

* v3.13c release

* back push (#952)

* Dev (#949)

* use atomic read-modify-write increment for LLVM CLASSIC

* Change other LLVM modes to atomic increments

* sync (#886)

* Create FUNDING.yml

* Update FUNDING.yml

* moved custom_mutator examples

* unicorn speedtest makefile cleanup

* fixed example location

* fix qdbi

* update util readme

* work in progress: not working correctly yet

* Frida persistent (#880)

* Added x64 support for persistent mode (function call only), in-memory teest cases and complog

* Review changes, fix NeverZero and code to parse the .text section of the main executable. Excluded ranges TBC

* Various minor fixes and finished support for AFL_INST_LIBS

* Review changes

Co-authored-by: Your Name <you@example.com>

* nits

* fix frida mode

* Integer overflow/underflow fixes in libdislocator (#889)

* libdislocator: fixing integer overflow in 'max_mem' variable and setting 'max_mem' type to 'size_t'

* libdislocator: fixing potential integer underflow in 'total_mem' variable due to its different values in different threads

* Bumped warnings up to the max and fixed remaining issues (#890)

Co-authored-by: Your Name <you@example.com>

* nits

* frida mode - support non-pie

* nits

* nit

* update grammar mutator

* Fixes for aarch64, OSX and other minor issues (#891)

Co-authored-by: Your Name <you@example.com>

* nits

* nits

* fix PCGUARD, build aflpp_driver with fPIC

* Added representative fuzzbench test and test for libxml (#893)

* Added representative fuzzbench test and test for libxml

* Added support for building FRIDA from source with FRIDA_SOURCE=1

Co-authored-by: Your Name <you@example.com>

* nits

* update changelog

* typos

* still not working

* fixed potential double free in custom trim (#881)

* error handling, freeing mem

* frida: complog -> cmplog

* fix statsd writing

* let aflpp_qemu_driver_hook.so build fail gracefully

* fix stdin trimming

* Support for AFL_ENTRYPOINT (#898)

Co-authored-by: Your Name <you@example.com>

* remove the input file .cur_input at the end of the fuzzing, if AFL_TMPDIR is used

* reverse push (#901)

* Create FUNDING.yml

* Update FUNDING.yml

* disable QEMU static pie

Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>

* clarify that no modifications are required.

* add new test for frida_mode (please review)

* typos

* fix persistent mode (64-bit)

* set ARCH for linux intel 32-bit for frida-gum-devkit

* prepare for 32-bit support (later)

* not on qemu 3 anymore

* unicorn mips fixes

* instrumentation further move to C++11 (#900)

* unicorn fixes

* first working NeverZero implementation

* more unicorn fixes

* Fix memory errors when trim causes testcase growth (#881) (#903)

* Revert "fixed potential double free in custom trim (#881)"

This reverts commit e9d2f72382cab75832721d859c3e731da071435d.

* Revert "fix custom trim for increasing data"

This reverts commit 86a8ef168dda766d2f25f15c15c4d3ecf21d0667.

* Fix memory errors when trim causes testcase growth

Modify trim_case_custom to avoid writing into in_buf because
some custom mutators can cause the testcase to grow rather than
shrink.

Instead of modifying in_buf directly, we write the update out
to the disk when trimming is complete, and then the caller is
responsible for refreshing the in-memory buffer from the file.

This is still a bit sketchy because it does need to modify q->len in
order to notify the upper layers that something changed, and it could
end up telling upper layer code that the q->len is *bigger* than
the buffer (q->testcase_buf) that contains it, which is asking
for trouble down the line somewhere...

* Fix an unlikely situation

Put back some `unlikely()` calls that were in
the e9d2f72382cab75832721d859c3e731da071435d commit that was
reverted.

* add some comments

* typo

* Exit on time (#904)

* Variable AFL_EXIT_ON_TIME description has been added.
Variables AFL_EXIT_ON_TIME and afl_exit_on_time has been added.
afl->exit_on_time variable initialization has been added.
The asignment of a value to the afl->afl_env.afl_exit_on_time variable from
environment variables has been added.
Code to exit on timeout if new path not found has been added.

* Type of afl_exit_on_time variable has been changed.
Variable exit_on_time has been added to the afl_state_t structure.

* Command `export AFL_EXIT_WHEN_DONE=1` has been added.

* Millisecond to second conversion has been added.
Call get_cur_time() has been added.

* Revert to using the saved current time value.

* Useless check has been removed.

* fix new path to custom-mutators

* ensure crashes/README.txt exists

* fix

* Changes to bump FRIDA version and to clone FRIDA repo in to build directory rather than use a submodule as the FRIDA build scripts don't like it (#906)

Co-authored-by: Your Name <you@example.com>

* Fix numeric overflow in cmplog implementation (#907)

Co-authored-by: Your Name <you@example.com>

* testcase fixes for unicorn

* remove merge conflict artifacts

* fix afl-plot

* Changes to remove binaries from frida_mode (#913)

Co-authored-by: Your Name <you@example.com>

* Frida cmplog fail fast (#914)

* Changes to remove binaries from frida_mode

* Changes to make cmplog fail fast

Co-authored-by: Your Name <you@example.com>

* afl-plot: relative time

* arch linux and mac os support for afl-system-config

* typo

* code-format

* update documentation

* github workflow for qemu

* OSX-specific improvements (#912)

* Fix afl-cc to work correctly by default on OSX using xcode

- CLANG_ENV_VAR must be set for afl-as to work
- Use clang mode by default if no specific compiler selected

* Add OSX-specific documentation for configuring shared memory

* Fixes to memory operands for complog (#916)

Co-authored-by: Your Name <you@example.com>

* fix a few cur_time uses

* added bounds check to pivot_inputs (fixes #921)

* additional safety checks for restarts

* restrict afl-showmap in_file size

* fix seed crash disable

* add warning for afl-showmap partial read

* no core dumps

* AFL_PRINT_FILENAMES added

* more documentation for AFL_EXIT_ON_TIME

* Flushing for AFL_PRINT_FILENAMES

* FASAN Support (#918)

* FASAN Support

* Fix handling of Address Sanitizer DSO

* Changes to identification of Address Sanitizer DSO

Co-authored-by: Your Name <you@example.com>

* Support for x86 (#920)

Co-authored-by: Your Name <you@example.com>

* Update frida_mode readme (#925)

* libqasan: use syscalls for read and write

* update readme

* Minor integration tweaks (#926)

Co-authored-by: Your Name <you@example.com>

* merge

* fix afl-fuzz.c frida preload

* cleaned up AFL_PRINT_FILENAMES env

* Changes to have persistent mode exit at the end of the loop (#928)

Co-authored-by: Your Name <you@example.com>

* fix llvm-dict2file

* push to stable (#931) (#932)

* sync (#886)

* Create FUNDING.yml

* Update FUNDING.yml

* moved custom_mutator examples

* unicorn speedtest makefile cleanup

* fixed example location

* fix qdbi

* update util readme

* Frida persistent (#880)

* Added x64 support for persistent mode (function call only), in-memory teest cases and complog

* Review changes, fix NeverZero and code to parse the .text section of the main executable. Excluded ranges TBC

* Various minor fixes and finished support for AFL_INST_LIBS

* Review changes

Co-authored-by: Your Name <you@example.com>

* nits

* fix frida mode

* Integer overflow/underflow fixes in libdislocator (#889)

* libdislocator: fixing integer overflow in 'max_mem' variable and setting 'max_mem' type to 'size_t'

* libdislocator: fixing potential integer underflow in 'total_mem' variable due to its different values in different threads

* Bumped warnings up to the max and fixed remaining issues (#890)

Co-authored-by: Your Name <you@example.com>

* nits

* frida mode - support non-pie

* nits

* nit

* update grammar mutator

* Fixes for aarch64, OSX and other minor issues (#891)

Co-authored-by: Your Name <you@example.com>

* nits

* nits

* fix PCGUARD, build aflpp_driver with fPIC

* Added representative fuzzbench test and test for libxml (#893)

* Added representative fuzzbench test and test for libxml

* Added support for building FRIDA from source with FRIDA_SOURCE=1

Co-authored-by: Your Name <you@example.com>

* nits

* update changelog

* typos

* fixed potential double free in custom trim (#881)

* error handling, freeing mem

* frida: complog -> cmplog

* fix statsd writing

* let aflpp_qemu_driver_hook.so build fail gracefully

* fix stdin trimming

* Support for AFL_ENTRYPOINT (#898)

Co-authored-by: Your Name <you@example.com>

* remove the input file .cur_input at the end of the fuzzing, if AFL_TMPDIR is used

* reverse push (#901)

* Create FUNDING.yml

* Update FUNDING.yml

* disable QEMU static pie

Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>

* clarify that no modifications are required.

* add new test for frida_mode (please review)

* typos

* fix persistent mode (64-bit)

* set ARCH for linux intel 32-bit for frida-gum-devkit

* prepare for 32-bit support (later)

* not on qemu 3 anymore

* unicorn mips fixes

* instrumentation further move to C++11 (#900)

* unicorn fixes

* more unicorn fixes

* Fix memory errors when trim causes testcase growth (#881) (#903)

* Revert "fixed potential double free in custom trim (#881)"

This reverts commit e9d2f72382cab75832721d859c3e731da071435d.

* Revert "fix custom trim for increasing data"

This reverts commit 86a8ef168dda766d2f25f15c15c4d3ecf21d0667.

* Fix memory errors when trim causes testcase growth

Modify trim_case_custom to avoid writing into in_buf because
some custom mutators can cause the testcase to grow rather than
shrink.

Instead of modifying in_buf directly, we write the update out
to the disk when trimming is complete, and then the caller is
responsible for refreshing the in-memory buffer from the file.

This is still a bit sketchy because it does need to modify q->len in
order to notify the upper layers that something changed, and it could
end up telling upper layer code that the q->len is *bigger* than
the buffer (q->testcase_buf) that contains it, which is asking
for trouble down the line somewhere...

* Fix an unlikely situation

Put back some `unlikely()` calls that were in
the e9d2f72382cab75832721d859c3e731da071435d commit that was
reverted.

* typo

* Exit on time (#904)

* Variable AFL_EXIT_ON_TIME description has been added.
Variables AFL_EXIT_ON_TIME and afl_exit_on_time has been added.
afl->exit_on_time variable initialization has been added.
The asignment of a value to the afl->afl_env.afl_exit_on_time variable from
environment variables has been added.
Code to exit on timeout if new path not found has been added.

* Type of afl_exit_on_time variable has been changed.
Variable exit_on_time has been added to the afl_state_t structure.

* Command `export AFL_EXIT_WHEN_DONE=1` has been added.

* Millisecond to second conversion has been added.
Call get_cur_time() has been added.

* Revert to using the saved current time value.

* Useless check has been removed.

* fix new path to custom-mutators

* ensure crashes/README.txt exists

* fix

* Changes to bump FRIDA version and to clone FRIDA repo in to build directory rather than use a submodule as the FRIDA build scripts don't like it (#906)

Co-authored-by: Your Name <you@example.com>

* Fix numeric overflow in cmplog implementation (#907)

Co-authored-by: Your Name <you@example.com>

* testcase fixes for unicorn

* remove merge conflict artifacts

* fix afl-plot

* Changes to remove binaries from frida_mode (#913)

Co-authored-by: Your Name <you@example.com>

* Frida cmplog fail fast (#914)

* Changes to remove binaries from frida_mode

* Changes to make cmplog fail fast

Co-authored-by: Your Name <you@example.com>

* afl-plot: relative time

* arch linux and mac os support for afl-system-config

* typo

* code-format

* update documentation

* github workflow for qemu

* OSX-specific improvements (#912)

* Fix afl-cc to work correctly by default on OSX using xcode

- CLANG_ENV_VAR must be set for afl-as to work
- Use clang mode by default if no specific compiler selected

* Add OSX-specific documentation for configuring shared memory

* Fixes to memory operands for complog (#916)

Co-authored-by: Your Name <you@example.com>

* fix a few cur_time uses

* added bounds check to pivot_inputs (fixes #921)

* additional safety checks for restarts

* restrict afl-showmap in_file size

* fix seed crash disable

* add warning for afl-showmap partial read

* no core dumps

* AFL_PRINT_FILENAMES added

* more documentation for AFL_EXIT_ON_TIME

* Flushing for AFL_PRINT_FILENAMES

* FASAN Support (#918)

* FASAN Support

* Fix handling of Address Sanitizer DSO

* Changes to identification of Address Sanitizer DSO

Co-authored-by: Your Name <you@example.com>

* Support for x86 (#920)

Co-authored-by: Your Name <you@example.com>

* Update frida_mode readme (#925)

* libqasan: use syscalls for read and write

* update readme

* Minor integration tweaks (#926)

Co-authored-by: Your Name <you@example.com>

* merge

* fix afl-fuzz.c frida preload

* cleaned up AFL_PRINT_FILENAMES env

* Changes to have persistent mode exit at the end of the loop (#928)

Co-authored-by: Your Name <you@example.com>

* fix llvm-dict2file

Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: hexcoder <hexcoder-@users.noreply.github.com>
Co-authored-by: hexcoder- <heiko@hexco.de>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>

Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: hexcoder <hexcoder-@users.noreply.github.com>
Co-authored-by: hexcoder- <heiko@hexco.de>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>

* improve error msg

* Added documentation for wine LoadLibrary workaround (#933)

* Fix cmake target compilation command example (#934)

- Fix typo DCMAKE_C_COMPILERC -> DCMAKE_C_COMPILER.
- Add `cd build` after `mkdir build`.

* showmap passes queue items in alphabetical order

* added tmp files to gitignore

* lenient dict parsing, no map size enum for binary fuzzing

* added info about showmap queue directions

* update binary-only doc

* turn off map size detection if skip_bin_check is set

* Typo

* update docs

* update afl-system-config

* Set kill signal before using it in afl-showmap (#935)

* fix afl-cc help output

* add libafl to binary-only doc

* update docs

* less executions on variable paths

* AFL_SKIP_CRASHES is obsolete since 3.0

* add AFL_TRY_AFFINITY

* Typo

* Typo

* Typo/wording

* tweaks

* typos

* fix afl-whatsup help output

* fix afl-plot output

* fix for MacOS

* fix cmpcov doc for qemu

* fix tmpfile removal

* update dockerfile

* Frida (#940)

* Added re2 test

* Added libpcap test

* Fix validation of setting of ADDR_NO_RANDOMIZE

* Added support for printing original and instrumented code

Co-authored-by: Your Name <you@example.com>

* Support for AFL_FRIDA_PERSISTENT_RET (#941)

Co-authored-by: Your Name <you@example.com>

* Changes to add missing exclusion of ranges (#943)

Co-authored-by: Your Name <you@example.com>

* add --afl-noopt to afl-cc

* docs: fix link to README in QuickStartGuide (#946)

* Support writing Stalker stats (#945)

* Support writing Stalker stats

* Fixed string handling in print functions

Co-authored-by: Your Name <you@example.com>

* afl-cmin help fix, aflpp_driver - + @@ support

* fix for afl-showmap

* support new env var AFL_LLVM_THREADSAFE_INST to enable atomic counters.
add new test case for that.

* add documentation for AFL_LLVM_THREADSAFE_INST

* add support for AFL_LLVM_THREADSAFE_INST to other LLVM passes

* add missing include for _exit()

* threadsafe doc fixes, code format

* Wording: "never zero" -> NeverZero

* fix afl_custom_post_process with multiple custom mutators

* fix docs

* debug ck_write

* fixed potential diff by 0

* fixes

* fix classic threadsafe counters

Co-authored-by: van Hauser <vh@thc.org>
Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>
Co-authored-by: 0x4d5a-ctf <51098072+0x4d5a-ctf@users.noreply.github.com>
Co-authored-by: Tommy Chiang <oToToT@users.noreply.github.com>
Co-authored-by: buherator <buherator@silentsignal.hu>
Co-authored-by: Dag Heyman Kajevic <dag.heyman@gmail.com>

* v3.13c release (#950)

* use atomic read-modify-write increment for LLVM CLASSIC

* Change other LLVM modes to atomic increments

* sync (#886)

* Create FUNDING.yml

* Update FUNDING.yml

* moved custom_mutator examples

* unicorn speedtest makefile cleanup

* fixed example location

* fix qdbi

* update util readme

* work in progress: not working correctly yet

* Frida persistent (#880)

* Added x64 support for persistent mode (function call only), in-memory teest cases and complog

* Review changes, fix NeverZero and code to parse the .text section of the main executable. Excluded ranges TBC

* Various minor fixes and finished support for AFL_INST_LIBS

* Review changes

Co-authored-by: Your Name <you@example.com>

* nits

* fix frida mode

* Integer overflow/underflow fixes in libdislocator (#889)

* libdislocator: fixing integer overflow in 'max_mem' variable and setting 'max_mem' type to 'size_t'

* libdislocator: fixing potential integer underflow in 'total_mem' variable due to its different values in different threads

* Bumped warnings up to the max and fixed remaining issues (#890)

Co-authored-by: Your Name <you@example.com>

* nits

* frida mode - support non-pie

* nits

* nit

* update grammar mutator

* Fixes for aarch64, OSX and other minor issues (#891)

Co-authored-by: Your Name <you@example.com>

* nits

* nits

* fix PCGUARD, build aflpp_driver with fPIC

* Added representative fuzzbench test and test for libxml (#893)

* Added representative fuzzbench test and test for libxml

* Added support for building FRIDA from source with FRIDA_SOURCE=1

Co-authored-by: Your Name <you@example.com>

* nits

* update changelog

* typos

* still not working

* fixed potential double free in custom trim (#881)

* error handling, freeing mem

* frida: complog -> cmplog

* fix statsd writing

* let aflpp_qemu_driver_hook.so build fail gracefully

* fix stdin trimming

* Support for AFL_ENTRYPOINT (#898)

Co-authored-by: Your Name <you@example.com>

* remove the input file .cur_input at the end of the fuzzing, if AFL_TMPDIR is used

* reverse push (#901)

* Create FUNDING.yml

* Update FUNDING.yml

* disable QEMU static pie

Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>

* clarify that no modifications are required.

* add new test for frida_mode (please review)

* typos

* fix persistent mode (64-bit)

* set ARCH for linux intel 32-bit for frida-gum-devkit

* prepare for 32-bit support (later)

* not on qemu 3 anymore

* unicorn mips fixes

* instrumentation further move to C++11 (#900)

* unicorn fixes

* first working NeverZero implementation

* more unicorn fixes

* Fix memory errors when trim causes testcase growth (#881) (#903)

* Revert "fixed potential double free in custom trim (#881)"

This reverts commit e9d2f72382cab75832721d859c3e731da071435d.

* Revert "fix custom trim for increasing data"

This reverts commit 86a8ef168dda766d2f25f15c15c4d3ecf21d0667.

* Fix memory errors when trim causes testcase growth

Modify trim_case_custom to avoid writing into in_buf because
some custom mutators can cause the testcase to grow rather than
shrink.

Instead of modifying in_buf directly, we write the update out
to the disk when trimming is complete, and then the caller is
responsible for refreshing the in-memory buffer from the file.

This is still a bit sketchy because it does need to modify q->len in
order to notify the upper layers that something changed, and it could
end up telling upper layer code that the q->len is *bigger* than
the buffer (q->testcase_buf) that contains it, which is asking
for trouble down the line somewhere...

* Fix an unlikely situation

Put back some `unlikely()` calls that were in
the e9d2f72382cab75832721d859c3e731da071435d commit that was
reverted.

* add some comments

* typo

* Exit on time (#904)

* Variable AFL_EXIT_ON_TIME description has been added.
Variables AFL_EXIT_ON_TIME and afl_exit_on_time has been added.
afl->exit_on_time variable initialization has been added.
The asignment of a value to the afl->afl_env.afl_exit_on_time variable from
environment variables has been added.
Code to exit on timeout if new path not found has been added.

* Type of afl_exit_on_time variable has been changed.
Variable exit_on_time has been added to the afl_state_t structure.

* Command `export AFL_EXIT_WHEN_DONE=1` has been added.

* Millisecond to second conversion has been added.
Call get_cur_time() has been added.

* Revert to using the saved current time value.

* Useless check has been removed.

* fix new path to custom-mutators

* ensure crashes/README.txt exists

* fix

* Changes to bump FRIDA version and to clone FRIDA repo in to build directory rather than use a submodule as the FRIDA build scripts don't like it (#906)

Co-authored-by: Your Name <you@example.com>

* Fix numeric overflow in cmplog implementation (#907)

Co-authored-by: Your Name <you@example.com>

* testcase fixes for unicorn

* remove merge conflict artifacts

* fix afl-plot

* Changes to remove binaries from frida_mode (#913)

Co-authored-by: Your Name <you@example.com>

* Frida cmplog fail fast (#914)

* Changes to remove binaries from frida_mode

* Changes to make cmplog fail fast

Co-authored-by: Your Name <you@example.com>

* afl-plot: relative time

* arch linux and mac os support for afl-system-config

* typo

* code-format

* update documentation

* github workflow for qemu

* OSX-specific improvements (#912)

* Fix afl-cc to work correctly by default on OSX using xcode

- CLANG_ENV_VAR must be set for afl-as to work
- Use clang mode by default if no specific compiler selected

* Add OSX-specific documentation for configuring shared memory

* Fixes to memory operands for complog (#916)

Co-authored-by: Your Name <you@example.com>

* fix a few cur_time uses

* added bounds check to pivot_inputs (fixes #921)

* additional safety checks for restarts

* restrict afl-showmap in_file size

* fix seed crash disable

* add warning for afl-showmap partial read

* no core dumps

* AFL_PRINT_FILENAMES added

* more documentation for AFL_EXIT_ON_TIME

* Flushing for AFL_PRINT_FILENAMES

* FASAN Support (#918)

* FASAN Support

* Fix handling of Address Sanitizer DSO

* Changes to identification of Address Sanitizer DSO

Co-authored-by: Your Name <you@example.com>

* Support for x86 (#920)

Co-authored-by: Your Name <you@example.com>

* Update frida_mode readme (#925)

* libqasan: use syscalls for read and write

* update readme

* Minor integration tweaks (#926)

Co-authored-by: Your Name <you@example.com>

* merge

* fix afl-fuzz.c frida preload

* cleaned up AFL_PRINT_FILENAMES env

* Changes to have persistent mode exit at the end of the loop (#928)

Co-authored-by: Your Name <you@example.com>

* fix llvm-dict2file

* push to stable (#931) (#932)

* sync (#886)

* Create FUNDING.yml

* Update FUNDING.yml

* moved custom_mutator examples

* unicorn speedtest makefile cleanup

* fixed example location

* fix qdbi

* update util readme

* Frida persistent (#880)

* Added x64 support for persistent mode (function call only), in-memory teest cases and complog

* Review changes, fix NeverZero and code to parse the .text section of the main executable. Excluded ranges TBC

* Various minor fixes and finished support for AFL_INST_LIBS

* Review changes

Co-authored-by: Your Name <you@example.com>

* nits

* fix frida mode

* Integer overflow/underflow fixes in libdislocator (#889)

* libdislocator: fixing integer overflow in 'max_mem' variable and setting 'max_mem' type to 'size_t'

* libdislocator: fixing potential integer underflow in 'total_mem' variable due to its different values in different threads

* Bumped warnings up to the max and fixed remaining issues (#890)

Co-authored-by: Your Name <you@example.com>

* nits

* frida mode - support non-pie

* nits

* nit

* update grammar mutator

* Fixes for aarch64, OSX and other minor issues (#891)

Co-authored-by: Your Name <you@example.com>

* nits

* nits

* fix PCGUARD, build aflpp_driver with fPIC

* Added representative fuzzbench test and test for libxml (#893)

* Added representative fuzzbench test and test for libxml

* Added support for building FRIDA from source with FRIDA_SOURCE=1

Co-authored-by: Your Name <you@example.com>

* nits

* update changelog

* typos

* fixed potential double free in custom trim (#881)

* error handling, freeing mem

* frida: complog -> cmplog

* fix statsd writing

* let aflpp_qemu_driver_hook.so build fail gracefully

* fix stdin trimming

* Support for AFL_ENTRYPOINT (#898)

Co-authored-by: Your Name <you@example.com>

* remove the input file .cur_input at the end of the fuzzing, if AFL_TMPDIR is used

* reverse push (#901)

* Create FUNDING.yml

* Update FUNDING.yml

* disable QEMU static pie

Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>

* clarify that no modifications are required.

* add new test for frida_mode (please review)

* typos

* fix persistent mode (64-bit)

* set ARCH for linux intel 32-bit for frida-gum-devkit

* prepare for 32-bit support (later)

* not on qemu 3 anymore

* unicorn mips fixes

* instrumentation further move to C++11 (#900)

* unicorn fixes

* more unicorn fixes

* Fix memory errors when trim causes testcase growth (#881) (#903)

* Revert "fixed potential double free in custom trim (#881)"

This reverts commit e9d2f72382cab75832721d859c3e731da071435d.

* Revert "fix custom trim for increasing data"

This reverts commit 86a8ef168dda766d2f25f15c15c4d3ecf21d0667.

* Fix memory errors when trim causes testcase growth

Modify trim_case_custom to avoid writing into in_buf because
some custom mutators can cause the testcase to grow rather than
shrink.

Instead of modifying in_buf directly, we write the update out
to the disk when trimming is complete, and then the caller is
responsible for refreshing the in-memory buffer from the file.

This is still a bit sketchy because it does need to modify q->len in
order to notify the upper layers that something changed, and it could
end up telling upper layer code that the q->len is *bigger* than
the buffer (q->testcase_buf) that contains it, which is asking
for trouble down the line somewhere...

* Fix an unlikely situation

Put back some `unlikely()` calls that were in
the e9d2f72382cab75832721d859c3e731da071435d commit that was
reverted.

* typo

* Exit on time (#904)

* Variable AFL_EXIT_ON_TIME description has been added.
Variables AFL_EXIT_ON_TIME and afl_exit_on_time has been added.
afl->exit_on_time variable initialization has been added.
The asignment of a value to the afl->afl_env.afl_exit_on_time variable from
environment variables has been added.
Code to exit on timeout if new path not found has been added.

* Type of afl_exit_on_time variable has been changed.
Variable exit_on_time has been added to the afl_state_t structure.

* Command `export AFL_EXIT_WHEN_DONE=1` has been added.

* Millisecond to second conversion has been added.
Call get_cur_time() has been added.

* Revert to using the saved current time value.

* Useless check has been removed.

* fix new path to custom-mutators

* ensure crashes/README.txt exists

* fix

* Changes to bump FRIDA version and to clone FRIDA repo in to build directory rather than use a submodule as the FRIDA build scripts don't like it (#906)

Co-authored-by: Your Name <you@example.com>

* Fix numeric overflow in cmplog implementation (#907)

Co-authored-by: Your Name <you@example.com>

* testcase fixes for unicorn

* remove merge conflict artifacts

* fix afl-plot

* Changes to remove binaries from frida_mode (#913)

Co-authored-by: Your Name <you@example.com>

* Frida cmplog fail fast (#914)

* Changes to remove binaries from frida_mode

* Changes to make cmplog fail fast

Co-authored-by: Your Name <you@example.com>

* afl-plot: relative time

* arch linux and mac os support for afl-system-config

* typo

* code-format

* update documentation

* github workflow for qemu

* OSX-specific improvements (#912)

* Fix afl-cc to work correctly by default on OSX using xcode

- CLANG_ENV_VAR must be set for afl-as to work
- Use clang mode by default if no specific compiler selected

* Add OSX-specific documentation for configuring shared memory

* Fixes to memory operands for complog (#916)

Co-authored-by: Your Name <you@example.com>

* fix a few cur_time uses

* added bounds check to pivot_inputs (fixes #921)

* additional safety checks for restarts

* restrict afl-showmap in_file size

* fix seed crash disable

* add warning for afl-showmap partial read

* no core dumps

* AFL_PRINT_FILENAMES added

* more documentation for AFL_EXIT_ON_TIME

* Flushing for AFL_PRINT_FILENAMES

* FASAN Support (#918)

* FASAN Support

* Fix handling of Address Sanitizer DSO

* Changes to identification of Address Sanitizer DSO

Co-authored-by: Your Name <you@example.com>

* Support for x86 (#920)

Co-authored-by: Your Name <you@example.com>

* Update frida_mode readme (#925)

* libqasan: use syscalls for read and write

* update readme

* Minor integration tweaks (#926)

Co-authored-by: Your Name <you@example.com>

* merge

* fix afl-fuzz.c frida preload

* cleaned up AFL_PRINT_FILENAMES env

* Changes to have persistent mode exit at the end of the loop (#928)

Co-authored-by: Your Name <you@example.com>

* fix llvm-dict2file

Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: hexcoder <hexcoder-@users.noreply.github.com>
Co-authored-by: hexcoder- <heiko@hexco.de>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>

Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: hexcoder <hexcoder-@users.noreply.github.com>
Co-authored-by: hexcoder- <heiko@hexco.de>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>

* improve error msg

* Added documentation for wine LoadLibrary workaround (#933)

* Fix cmake target compilation command example (#934)

- Fix typo DCMAKE_C_COMPILERC -> DCMAKE_C_COMPILER.
- Add `cd build` after `mkdir build`.

* showmap passes queue items in alphabetical order

* added tmp files to gitignore

* lenient dict parsing, no map size enum for binary fuzzing

* added info about showmap queue directions

* update binary-only doc

* turn off map size detection if skip_bin_check is set

* Typo

* update docs

* update afl-system-config

* Set kill signal before using it in afl-showmap (#935)

* fix afl-cc help output

* add libafl to binary-only doc

* update docs

* less executions on variable paths

* AFL_SKIP_CRASHES is obsolete since 3.0

* add AFL_TRY_AFFINITY

* Typo

* Typo

* Typo/wording

* tweaks

* typos

* fix afl-whatsup help output

* fix afl-plot output

* fix for MacOS

* fix cmpcov doc for qemu

* fix tmpfile removal

* update dockerfile

* Frida (#940)

* Added re2 test

* Added libpcap test

* Fix validation of setting of ADDR_NO_RANDOMIZE

* Added support for printing original and instrumented code

Co-authored-by: Your Name <you@example.com>

* Support for AFL_FRIDA_PERSISTENT_RET (#941)

Co-authored-by: Your Name <you@example.com>

* Changes to add missing exclusion of ranges (#943)

Co-authored-by: Your Name <you@example.com>

* add --afl-noopt to afl-cc

* docs: fix link to README in QuickStartGuide (#946)

* Support writing Stalker stats (#945)

* Support writing Stalker stats

* Fixed string handling in print functions

Co-authored-by: Your Name <you@example.com>

* afl-cmin help fix, aflpp_driver - + @@ support

* fix for afl-showmap

* support new env var AFL_LLVM_THREADSAFE_INST to enable atomic counters.
add new test case for that.

* add documentation for AFL_LLVM_THREADSAFE_INST

* add support for AFL_LLVM_THREADSAFE_INST to other LLVM passes

* add missing include for _exit()

* threadsafe doc fixes, code format

* Wording: "never zero" -> NeverZero

* fix afl_custom_post_process with multiple custom mutators

* fix docs

* debug ck_write

* fixed potential diff by 0

* fixes

* fix classic threadsafe counters

* v3.13c release

Co-authored-by: hexcoder- <heiko@hexco.de>
Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: hexcoder <hexcoder-@users.noreply.github.com>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>
Co-authored-by: 0x4d5a-ctf <51098072+0x4d5a-ctf@users.noreply.github.com>
Co-authored-by: Tommy Chiang <oToToT@users.noreply.github.com>
Co-authored-by: buherator <buherator@silentsignal.hu>
Co-authored-by: Dag Heyman Kajevic <dag.heyman@gmail.com>

Co-authored-by: hexcoder <hexcoder-@users.noreply.github.com>
Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>
Co-authored-by: 0x4d5a-ctf <51098072+0x4d5a-ctf@users.noreply.github.com>
Co-authored-by: Tommy Chiang <oToToT@users.noreply.github.com>
Co-authored-by: buherator <buherator@silentsignal.hu>
Co-authored-by: Dag Heyman Kajevic <dag.heyman@gmail.com>
Co-authored-by: hexcoder- <heiko@hexco.de>

* v3.14a init

* remove redundant unsetenv (#947)

* update MacOS Install information

* add missing clean action for frida_mode

* ensure memory is there before free

* adapt to incompatible LLVM 13 API

* fix stupid typos

* add fix info

* build afl-compiler-rt even with broken llvm

* fix -F with slash option

* dynamic_list and afl-compiler-rt rework

* detect partial linking in afl-cc

* partial linking with -Wl

* Add proper name and URL for Zafl (#959)

* move link

* add known frontends for supported compiler infrastructures

* add Rust

* fix ui fuzzing stage index (#960)

* fix overflowing UI fields 'now processing'

* restored timeout handling (with SIGALRM for now)

* On non-Linux systems make clean may fail for frida_mode

* give hint how to set env var for path to llvm-config tool

* setting AFL_CC for test-llvm.sh on FreeBSD is not necessary anymore

* remove -D from -M

* write target errors to out_dir/error.txt

* add changelog entry

* add changelog

* format

* more info for error logging

* Forkserver for afl-analyze (#963)

* afl-analyze forkserver

* added missing vars to forkserver

* synchronized a bit more with afl-tmin

* more debugging, runs now, but need to suppress target output

* fix dev/null setting

* afl-analyze info:

Co-authored-by: hexcoder- <heiko@hexco.de>

* proper newlines

* reenable LLVM 3.8 ( Ubuntu 16.04 )

* FRIDA AARCH64 support (#965)

Co-authored-by: Your Name <you@example.com>

* adapt docs to minimum LLVM version

* adapt to minimum llvm version

* remove warning regarding core_pattern (was wrong/unnecessary anyway)

* avoid code duplication, symlink header file

* clippy fixes

* add test cases for splitting integer comparisons

* Revert "add test cases for splitting integer comparisons"

This reverts commit e0aa411647e1a525a3a0488d929ec71611388d54.

* add test cases for splitting integer comparisons

* FRIDA - Remove need for AFL_FRIDA_PERSISTENT_RETADDR_OFFSET (#970)

Co-authored-by: Your Name <you@example.com>

* fix AFL_CAL_FAST

* fix cmplog screen update crash

* Frida complog fix (#971)

* Fix complog issue with changing address space

* Added support for printing command line and environment during startup

* Review fixes

Co-authored-by: Your Name <you@example.com>

* Improve tracing support to include real addresses and edge ids and also support logging edges only once (#972)

Co-authored-by: Your Name <you@example.com>

* split-comparison llvm pass refactor for smaller compilation times (and a small bug fix) (#964)

* Refactored split compare pass to be more efficient in LTO usage and allow splitting to other minimum bitwidths.

Efficiency: avoid looping over the whole llvm module N times, when once is also enough.

Bitwidth: Previously, due to fallthrough in switch-case, all comparisons were split to 8-bit, which might not be desirable e.g., 16 or 32 bit might be enough. So now all comparison are split until they are smaller or equal to the target bitwidth, which is controlled through the `AFL_LLVM_LAF_SPLIT_COMPARES_BITW` environment variable.

* fixed miscompilation due to incorrectly trying to split a signed comparison operator

* minor formatting updates and use IRBuilder when inserting multiple instructions

* added @hexcoder-'s test-int_cases.c to make test

* Avoid recursion; switch to smallvector in splitAndSimplify; use switch case for icmp type;

* Fixed issue when splitting < where the inverse comparison was not further split

* some cleanup

* code format

* fix to instrument global c++ namespace functions

* update changelog

* document frida changes

* Fix typo in README.md (#974)

* adapt for LLVM 3.8.0

* fix README

* little inline

* Add debug output to alert user to calibration progress/issues (#969)

* aflppdriver help output

* code format

Co-authored-by: hexcoder- <heiko@hexco.de>
Co-authored-by: Dominik Maier <domenukk@gmail.com>
Co-authored-by: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>
Co-authored-by: Your Name <you@example.com>
Co-authored-by: Dmitry Zheregelya <zheregelya.d@gmail.com>
Co-authored-by: hexcoder <hexcoder-@users.noreply.github.com>
Co-authored-by: Andrea Fioraldi <andreafioraldi@gmail.com>
Co-authored-by: David CARLIER <devnexen@gmail.com>
Co-authored-by: realmadsci <71108352+realmadsci@users.noreply.github.com>
Co-authored-by: Roman M. Iudichev <SecNotice@ya.ru>
Co-authored-by: Dustin Spicuzza <dustin@virtualroadside.com>
Co-authored-by: 0x4d5a-ctf <51098072+0x4d5a-ctf@users.noreply.github.com>
Co-authored-by: Tommy Chiang <oToToT@users.noreply.github.com>
Co-authored-by: buherator <buherator@silentsignal.hu>
Co-authored-by: Dag Heyman Kajevic <dag.heyman@gmail.com>
Co-authored-by: terrynini <terrynini38514@gmail.com>
Co-authored-by: jdhiser <hiser@virginia.edu>
Co-authored-by: yuan <ssspeed00@gmail.com>
Co-authored-by: Michael Rodler <michael.rodler@paluno.uni-due.de>
Co-authored-by: Artis <32833063+Artis24106@users.noreply.github.com>
2021-06-14 23:48:47 +02:00

2814 lines
62 KiB
C

/*
american fuzzy lop++ - redqueen implementation on top of cmplog
---------------------------------------------------------------
Originally written by Michal Zalewski
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0
Shared code to handle the shared memory. This is used by the fuzzer
as well the other components like afl-tmin, afl-showmap, etc...
*/
#include <limits.h>
#include "afl-fuzz.h"
#include "cmplog.h"
//#define _DEBUG
//#define CMPLOG_INTROSPECTION
// CMP attribute enum
enum {
IS_EQUAL = 1, // arithemtic equal comparison
IS_GREATER = 2, // arithmetic greater comparison
IS_LESSER = 4, // arithmetic lesser comparison
IS_FP = 8, // is a floating point, not an integer
/* --- below are internal settings, not from target cmplog */
IS_FP_MOD = 16, // arithemtic changed floating point
IS_INT_MOD = 32, // arithmetic changed interger
IS_TRANSFORM = 64 // transformed integer
};
// CMPLOG LVL
enum {
LVL1 = 1, // Integer solving
LVL2 = 2, // unused except for setting the queue entry
LVL3 = 4 // expensive tranformations
};
struct range {
u32 start;
u32 end;
struct range *next;
struct range *prev;
u8 ok;
};
static struct range *add_range(struct range *ranges, u32 start, u32 end) {
struct range *r = ck_alloc_nozero(sizeof(struct range));
r->start = start;
r->end = end;
r->next = ranges;
r->ok = 0;
if (likely(ranges)) ranges->prev = r;
return r;
}
static struct range *pop_biggest_range(struct range **ranges) {
struct range *r = *ranges;
struct range *rmax = NULL;
u32 max_size = 0;
while (r) {
if (!r->ok) {
u32 s = 1 + r->end - r->start;
if (s >= max_size) {
max_size = s;
rmax = r;
}
}
r = r->next;
}
return rmax;
}
#ifdef _DEBUG
// static int logging = 0;
static void dump(char *txt, u8 *buf, u32 len) {
u32 i;
fprintf(stderr, "DUMP %s %016llx ", txt, hash64(buf, len, HASH_CONST));
for (i = 0; i < len; i++)
fprintf(stderr, "%02x", buf[i]);
fprintf(stderr, "\n");
}
static void dump_file(char *path, char *name, u32 counter, u8 *buf, u32 len) {
char fn[4096];
if (!path) path = ".";
snprintf(fn, sizeof(fn), "%s/%s%d", path, name, counter);
int fd = open(fn, O_RDWR | O_CREAT | O_TRUNC, 0644);
if (fd >= 0) {
write(fd, buf, len);
close(fd);
}
}
#endif
static u8 get_exec_checksum(afl_state_t *afl, u8 *buf, u32 len, u64 *cksum) {
if (unlikely(common_fuzz_stuff(afl, buf, len))) { return 1; }
*cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
return 0;
}
/* replace everything with different values but stay in the same type */
static void type_replace(afl_state_t *afl, u8 *buf, u32 len) {
u32 i;
u8 c;
for (i = 0; i < len; ++i) {
// wont help for UTF or non-latin charsets
do {
switch (buf[i]) {
case 'A' ... 'F':
c = 'A' + rand_below(afl, 1 + 'F' - 'A');
break;
case 'a' ... 'f':
c = 'a' + rand_below(afl, 1 + 'f' - 'a');
break;
case '0':
c = '1';
break;
case '1':
c = '0';
break;
case '2' ... '9':
c = '2' + rand_below(afl, 1 + '9' - '2');
break;
case 'G' ... 'Z':
c = 'G' + rand_below(afl, 1 + 'Z' - 'G');
break;
case 'g' ... 'z':
c = 'g' + rand_below(afl, 1 + 'z' - 'g');
break;
case '!' ... '*':
c = '!' + rand_below(afl, 1 + '*' - '!');
break;
case ',' ... '.':
c = ',' + rand_below(afl, 1 + '.' - ',');
break;
case ':' ... '@':
c = ':' + rand_below(afl, 1 + '@' - ':');
break;
case '[' ... '`':
c = '[' + rand_below(afl, 1 + '`' - '[');
break;
case '{' ... '~':
c = '{' + rand_below(afl, 1 + '~' - '{');
break;
case '+':
c = '/';
break;
case '/':
c = '+';
break;
case ' ':
c = '\t';
break;
case '\t':
c = ' ';
break;
case '\r':
c = '\n';
break;
case '\n':
c = '\r';
break;
case 0:
c = 1;
break;
case 1:
c = 0;
break;
case 0xff:
c = 0;
break;
default:
if (buf[i] < 32) {
c = (buf[i] ^ 0x1f);
} else {
c = (buf[i] ^ 0x7f); // we keep the highest bit
}
}
} while (c == buf[i]);
buf[i] = c;
}
}
static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
struct tainted **taints) {
struct range * ranges = add_range(NULL, 0, len - 1), *rng;
struct tainted *taint = NULL;
u8 * backup = ck_alloc_nozero(len);
u8 * changed = ck_alloc_nozero(len);
#if defined(_DEBUG) || defined(CMPLOG_INTROSPECTION)
u64 start_time = get_cur_time();
#endif
u32 screen_update;
u64 orig_hit_cnt, new_hit_cnt, exec_cksum;
orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
afl->stage_name = "colorization";
afl->stage_short = "colorization";
afl->stage_max = (len << 1);
afl->stage_cur = 0;
if (likely(afl->queue_cur->exec_us)) {
if (likely((100000 / 2) >= afl->queue_cur->exec_us)) {
screen_update = 100000 / afl->queue_cur->exec_us;
} else {
screen_update = 1;
}
} else {
screen_update = 100000;
}
// in colorization we do not classify counts, hence we have to calculate
// the original checksum.
if (unlikely(get_exec_checksum(afl, buf, len, &exec_cksum))) {
goto checksum_fail;
}
memcpy(backup, buf, len);
memcpy(changed, buf, len);
type_replace(afl, changed, len);
while ((rng = pop_biggest_range(&ranges)) != NULL &&
afl->stage_cur < afl->stage_max) {
u32 s = 1 + rng->end - rng->start;
memcpy(buf + rng->start, changed + rng->start, s);
u64 cksum = 0;
u64 start_us = get_cur_time_us();
if (unlikely(get_exec_checksum(afl, buf, len, &cksum))) {
goto checksum_fail;
}
u64 stop_us = get_cur_time_us();
/* Discard if the mutations change the path or if it is too decremental
in speed - how could the same path have a much different speed
though ...*/
if (cksum != exec_cksum ||
(unlikely(stop_us - start_us > 3 * afl->queue_cur->exec_us) &&
likely(!afl->fixed_seed))) {
memcpy(buf + rng->start, backup + rng->start, s);
if (s > 1) { // to not add 0 size ranges
ranges = add_range(ranges, rng->start, rng->start - 1 + s / 2);
ranges = add_range(ranges, rng->start + s / 2, rng->end);
}
if (ranges == rng) {
ranges = rng->next;
if (ranges) { ranges->prev = NULL; }
} else if (rng->next) {
rng->prev->next = rng->next;
rng->next->prev = rng->prev;
} else {
if (rng->prev) { rng->prev->next = NULL; }
}
free(rng);
} else {
rng->ok = 1;
}
if (++afl->stage_cur % screen_update) { show_stats(afl); };
}
rng = ranges;
while (rng) {
rng = rng->next;
}
u32 i = 1;
u32 positions = 0;
while (i) {
restart:
i = 0;
struct range *r = NULL;
u32 pos = (u32)-1;
rng = ranges;
while (rng) {
if (rng->ok == 1 && rng->start < pos) {
if (taint && taint->pos + taint->len == rng->start) {
taint->len += (1 + rng->end - rng->start);
positions += (1 + rng->end - rng->start);
rng->ok = 2;
goto restart;
} else {
r = rng;
pos = rng->start;
}
}
rng = rng->next;
}
if (r) {
struct tainted *t = ck_alloc_nozero(sizeof(struct tainted));
t->pos = r->start;
t->len = 1 + r->end - r->start;
positions += (1 + r->end - r->start);
if (likely(taint)) { taint->prev = t; }
t->next = taint;
t->prev = NULL;
taint = t;
r->ok = 2;
i = 1;
}
}
/* temporary: clean ranges */
while (ranges) {
rng = ranges;
ranges = rng->next;
ck_free(rng);
rng = NULL;
}
new_hit_cnt = afl->queued_paths + afl->unique_crashes;
#if defined(_DEBUG) || defined(CMPLOG_INTROSPECTION)
FILE *f = stderr;
#ifndef _DEBUG
if (afl->not_on_tty) {
char fn[4096];
snprintf(fn, sizeof(fn), "%s/introspection_cmplog.txt", afl->out_dir);
f = fopen(fn, "a");
}
#endif
if (f) {
fprintf(
f,
"Colorization: fname=%s len=%u ms=%llu result=%u execs=%u found=%llu "
"taint=%u\n",
afl->queue_cur->fname, len, get_cur_time() - start_time,
afl->queue_cur->colorized, afl->stage_cur, new_hit_cnt - orig_hit_cnt,
positions);
#ifndef _DEBUG
if (afl->not_on_tty) { fclose(f); }
#endif
}
#endif
if (taint) {
if (afl->colorize_success && afl->cmplog_lvl < 3 &&
(positions > CMPLOG_POSITIONS_MAX && len / positions == 1 &&
afl->active_paths / afl->colorize_success > CMPLOG_CORPUS_PERCENT)) {
#ifdef _DEBUG
fprintf(stderr, "Colorization unsatisfactory\n");
#endif
*taints = NULL;
struct tainted *t;
while (taint) {
t = taint->next;
ck_free(taint);
taint = t;
}
} else {
*taints = taint;
++afl->colorize_success;
}
}
afl->stage_finds[STAGE_COLORIZATION] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_COLORIZATION] += afl->stage_cur;
ck_free(backup);
ck_free(changed);
return 0;
checksum_fail:
while (ranges) {
rng = ranges;
ranges = rng->next;
ck_free(rng);
rng = NULL;
}
ck_free(backup);
ck_free(changed);
return 1;
}
///// Input to State replacement
static u8 its_fuzz(afl_state_t *afl, u8 *buf, u32 len, u8 *status) {
u64 orig_hit_cnt, new_hit_cnt;
orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
#ifdef _DEBUG
dump("DATA", buf, len);
#endif
if (unlikely(common_fuzz_stuff(afl, buf, len))) { return 1; }
new_hit_cnt = afl->queued_paths + afl->unique_crashes;
if (unlikely(new_hit_cnt != orig_hit_cnt)) {
#ifdef _DEBUG
fprintf(stderr, "NEW FIND\n");
#endif
*status = 1;
} else {
*status = 2;
}
return 0;
}
//#ifdef CMPLOG_SOLVE_TRANSFORM
static int strntoll(const char *str, size_t sz, char **end, int base,
long long *out) {
char buf[64];
long long ret;
const char *beg = str;
if (!str || !sz) { return 1; }
for (; beg && sz && *beg == ' '; beg++, sz--) {};
if (!sz) return 1;
if (sz >= sizeof(buf)) sz = sizeof(buf) - 1;
memcpy(buf, beg, sz);
buf[sz] = '\0';
ret = strtoll(buf, end, base);
if ((ret == LLONG_MIN || ret == LLONG_MAX) && errno == ERANGE) return 1;
if (end) *end = (char *)beg + (*end - buf);
*out = ret;
return 0;
}
static int strntoull(const char *str, size_t sz, char **end, int base,
unsigned long long *out) {
char buf[64];
unsigned long long ret;
const char * beg = str;
if (!str || !sz) { return 1; }
for (; beg && sz && *beg == ' '; beg++, sz--)
;
if (!sz) return 1;
if (sz >= sizeof(buf)) sz = sizeof(buf) - 1;
memcpy(buf, beg, sz);
buf[sz] = '\0';
ret = strtoull(buf, end, base);
if (ret == ULLONG_MAX && errno == ERANGE) return 1;
if (end) *end = (char *)beg + (*end - buf);
*out = ret;
return 0;
}
static u8 hex_table_up[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
static u8 hex_table_low[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
static u8 hex_table[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0,
0, 0, 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 10, 11, 12, 13, 14, 15};
// tests 2 bytes at location
static int is_hex(const char *str) {
u32 i;
for (i = 0; i < 2; i++) {
switch (str[i]) {
case '0' ... '9':
case 'A' ... 'F':
case 'a' ... 'f':
break;
default:
return 0;
}
}
return 1;
}
#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
// tests 4 bytes at location
static int is_base64(const char *str) {
u32 i;
for (i = 0; i < 4; i++) {
switch (str[i]) {
case '0' ... '9':
case 'A' ... 'Z':
case 'a' ... 'z':
case '+':
case '/':
case '=':
break;
default:
return 0;
}
}
return 1;
}
static u8 base64_encode_table[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
static u8 base64_decode_table[] = {
62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0,
0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
0, 0, 0, 0, 0, 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51};
static u32 from_base64(u8 *src, u8 *dst, u32 dst_len) {
u32 i, j, v;
u32 len = ((dst_len / 3) << 2);
u32 ret = 0;
for (i = 0, j = 0; i < len; i += 4, j += 3) {
v = base64_decode_table[src[i] - 43];
v = (v << 6) | base64_decode_table[src[i + 1] - 43];
v = src[i + 2] == '=' ? v << 6
: (v << 6) | base64_decode_table[src[i + 2] - 43];
v = src[i + 3] == '=' ? v << 6
: (v << 6) | base64_decode_table[src[i + 3] - 43];
dst[j] = (v >> 16) & 0xFF;
++ret;
if (src[i + 2] != '=') {
dst[j + 1] = (v >> 8) & 0xFF;
++ret;
}
if (src[i + 3] != '=') {
dst[j + 2] = v & 0xFF;
++ret;
}
}
return ret;
}
static void to_base64(u8 *src, u8 *dst, u32 dst_len) {
u32 i, j, v;
u32 len = (dst_len >> 2) * 3;
for (i = 0, j = 0; i < len; i += 3, j += 4) {
v = src[i];
v = i + 1 < len ? v << 8 | src[i + 1] : v << 8;
v = i + 2 < len ? v << 8 | src[i + 2] : v << 8;
dst[j] = base64_encode_table[(v >> 18) & 0x3F];
dst[j + 1] = base64_encode_table[(v >> 12) & 0x3F];
if (i + 1 < len) {
dst[j + 2] = base64_encode_table[(v >> 6) & 0x3F];
} else {
dst[j + 2] = '=';
}
if (i + 2 < len) {
dst[j + 3] = base64_encode_table[v & 0x3F];
} else {
dst[j + 3] = '=';
}
}
}
#endif
//#endif
static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
u64 pattern, u64 repl, u64 o_pattern,
u64 changed_val, u8 attr, u32 idx, u32 taint_len,
u8 *orig_buf, u8 *buf, u8 *cbuf, u32 len,
u8 do_reverse, u8 lvl, u8 *status) {
u64 *buf_64 = (u64 *)&buf[idx];
u32 *buf_32 = (u32 *)&buf[idx];
u16 *buf_16 = (u16 *)&buf[idx];
u8 * buf_8 = &buf[idx];
u64 *o_buf_64 = (u64 *)&orig_buf[idx];
u32 *o_buf_32 = (u32 *)&orig_buf[idx];
u16 *o_buf_16 = (u16 *)&orig_buf[idx];
u8 * o_buf_8 = &orig_buf[idx];
u32 its_len = MIN(len - idx, taint_len);
// fprintf(stderr,
// "Encode: %llx->%llx into %llx(<-%llx) at idx=%u "
// "taint_len=%u shape=%u attr=%u\n",
// o_pattern, pattern, repl, changed_val, idx, taint_len,
// h->shape + 1, attr);
//#ifdef CMPLOG_SOLVE_TRANSFORM
// reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3
if (afl->cmplog_enable_transform && (lvl & LVL3)) {
u8 * endptr;
u8 use_num = 0, use_unum = 0;
unsigned long long unum;
long long num;
if (afl->queue_cur->is_ascii) {
endptr = buf_8;
if (strntoll(buf_8, len - idx, (char **)&endptr, 0, &num)) {
if (!strntoull(buf_8, len - idx, (char **)&endptr, 0, &unum))
use_unum = 1;
} else
use_num = 1;
}
#ifdef _DEBUG
if (idx == 0)
fprintf(stderr, "ASCII is=%u use_num=%u use_unum=%u idx=%u %llx==%llx\n",
afl->queue_cur->is_ascii, use_num, use_unum, idx, num, pattern);
#endif
// num is likely not pattern as atoi("AAA") will be zero...
if (use_num && ((u64)num == pattern || !num)) {
u8 tmp_buf[32];
size_t num_len = snprintf(tmp_buf, sizeof(tmp_buf), "%lld", repl);
size_t old_len = endptr - buf_8;
u8 *new_buf = afl_realloc((void **)&afl->out_scratch_buf, len + num_len);
if (unlikely(!new_buf)) { PFATAL("alloc"); }
memcpy(new_buf, buf, idx);
memcpy(new_buf + idx, tmp_buf, num_len);
memcpy(new_buf + idx + num_len, buf_8 + old_len, len - idx - old_len);
if (new_buf[idx + num_len] >= '0' && new_buf[idx + num_len] <= '9') {
new_buf[idx + num_len] = ' ';
}
if (unlikely(its_fuzz(afl, new_buf, len, status))) { return 1; }
} else if (use_unum && (unum == pattern || !unum)) {
u8 tmp_buf[32];
size_t num_len = snprintf(tmp_buf, sizeof(tmp_buf), "%llu", repl);
size_t old_len = endptr - buf_8;
u8 *new_buf = afl_realloc((void **)&afl->out_scratch_buf, len + num_len);
if (unlikely(!new_buf)) { PFATAL("alloc"); }
memcpy(new_buf, buf, idx);
memcpy(new_buf + idx, tmp_buf, num_len);
memcpy(new_buf + idx + num_len, buf_8 + old_len, len - idx - old_len);
if (new_buf[idx + num_len] >= '0' && new_buf[idx + num_len] <= '9') {
new_buf[idx + num_len] = ' ';
}
if (unlikely(its_fuzz(afl, new_buf, len, status))) { return 1; }
}
// Try to identify transform magic
if (pattern != o_pattern && repl == changed_val && attr <= IS_EQUAL) {
u64 b_val, o_b_val, mask;
u8 bytes;
switch (SHAPE_BYTES(h->shape)) {
case 0:
case 1:
bytes = 1;
break;
case 2:
bytes = 2;
break;
case 3:
case 4:
bytes = 4;
break;
default:
bytes = 8;
}
// necessary for preventing heap access overflow
bytes = MIN(bytes, len - idx);
switch (bytes) {
case 0: // cannot happen
b_val = o_b_val = mask = 0; // keep the linters happy
break;
case 1: {
u8 *ptr = (u8 *)&buf[idx];
u8 *o_ptr = (u8 *)&orig_buf[idx];
b_val = (u64)(*ptr);
o_b_val = (u64)(*o_ptr % 0x100);
mask = 0xff;
break;
}
case 2:
case 3: {
u16 *ptr = (u16 *)&buf[idx];
u16 *o_ptr = (u16 *)&orig_buf[idx];
b_val = (u64)(*ptr);
o_b_val = (u64)(*o_ptr);
mask = 0xffff;
break;
}
case 4:
case 5:
case 6:
case 7: {
u32 *ptr = (u32 *)&buf[idx];
u32 *o_ptr = (u32 *)&orig_buf[idx];
b_val = (u64)(*ptr);
o_b_val = (u64)(*o_ptr);
mask = 0xffffffff;
break;
}
default: {
u64 *ptr = (u64 *)&buf[idx];
u64 *o_ptr = (u64 *)&orig_buf[idx];
b_val = (u64)(*ptr);
o_b_val = (u64)(*o_ptr);
mask = 0xffffffffffffffff;
}
}
// test for arithmetic, eg. "if ((user_val - 0x1111) == 0x1234) ..."
s64 diff = pattern - b_val;
s64 o_diff = o_pattern - o_b_val;
/* fprintf(stderr, "DIFF1 idx=%03u shape=%02u %llx-%llx=%lx\n", idx,
h->shape + 1, o_pattern, o_b_val, o_diff);
fprintf(stderr, "DIFF1 %016llx %llx-%llx=%lx\n", repl, pattern,
b_val, diff); */
if (diff == o_diff && diff) {
// this could be an arithmetic transformation
u64 new_repl = (u64)((s64)repl - diff);
// fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
if (unlikely(cmp_extend_encoding(
afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx,
taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
return 1;
}
// if (*status == 1) { fprintf(stderr, "FOUND!\n"); }
}
// test for XOR, eg. "if ((user_val ^ 0xabcd) == 0x1234) ..."
if (*status != 1) {
diff = pattern ^ b_val;
s64 o_diff = o_pattern ^ o_b_val;
/* fprintf(stderr, "DIFF2 idx=%03u shape=%02u %llx-%llx=%lx\n",
idx, h->shape + 1, o_pattern, o_b_val, o_diff);
fprintf(stderr,
"DIFF2 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);
*/
if (diff == o_diff && diff) {
// this could be a XOR transformation
u64 new_repl = (u64)((s64)repl ^ diff);
// fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
if (unlikely(cmp_extend_encoding(
afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx,
taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
return 1;
}
// if (*status == 1) { fprintf(stderr, "FOUND!\n"); }
}
}
// test for to lowercase, eg. "new_val = (user_val | 0x2020) ..."
if (*status != 1) {
if ((b_val | (0x2020202020202020 & mask)) == (pattern & mask)) {
diff = 1;
} else {
diff = 0;
}
if ((o_b_val | (0x2020202020202020 & mask)) == (o_pattern & mask)) {
o_diff = 1;
} else {
diff = 0;
}
/* fprintf(stderr, "DIFF3 idx=%03u shape=%02u %llx-%llx=%lx\n",
idx, h->shape + 1, o_pattern, o_b_val, o_diff);
fprintf(stderr,
"DIFF3 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);
*/
if (o_diff && diff) {
// this could be a lower to upper
u64 new_repl = (repl & (0x5f5f5f5f5f5f5f5f & mask));
// fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
if (unlikely(cmp_extend_encoding(
afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx,
taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
return 1;
}
// if (*status == 1) { fprintf(stderr, "FOUND!\n"); }
}
}
// test for to uppercase, eg. "new_val = (user_val | 0x5f5f) ..."
if (*status != 1) {
if ((b_val & (0x5f5f5f5f5f5f5f5f & mask)) == (pattern & mask)) {
diff = 1;
} else {
diff = 0;
}
if ((o_b_val & (0x5f5f5f5f5f5f5f5f & mask)) == (o_pattern & mask)) {
o_diff = 1;
} else {
o_diff = 0;
}
/* fprintf(stderr, "DIFF4 idx=%03u shape=%02u %llx-%llx=%lx\n",
idx, h->shape + 1, o_pattern, o_b_val, o_diff);
fprintf(stderr,
"DIFF4 %016llx %llx-%llx=%lx\n", repl, pattern, b_val, diff);
*/
if (o_diff && diff) {
// this could be a lower to upper
u64 new_repl = (repl | (0x2020202020202020 & mask));
// fprintf(stderr, "SAME DIFF %llx->%llx\n", repl, new_repl);
if (unlikely(cmp_extend_encoding(
afl, h, pattern, new_repl, o_pattern, repl, IS_TRANSFORM, idx,
taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
return 1;
}
// if (*status == 1) { fprintf(stderr, "FOUND!\n"); }
}
}
*status = 0;
}
}
//#endif
// we only allow this for ascii2integer (above) so leave if this is the case
if (unlikely(pattern == o_pattern)) { return 0; }
if ((lvl & LVL1) || attr >= IS_FP_MOD) {
if (SHAPE_BYTES(h->shape) >= 8 && *status != 1) {
// if (its_len >= 8)
// fprintf(stderr,
// "TestU64: %u>=8 (idx=%u attr=%u) %llx==%llx"
// " %llx==%llx <= %llx<-%llx\n",
// its_len, idx, attr, *buf_64, pattern, *o_buf_64, o_pattern,
// repl, changed_val);
// if this is an fcmp (attr & 8 == 8) then do not compare the patterns -
// due to a bug in llvm dynamic float bitcasts do not work :(
// the value 16 means this is a +- 1.0 test case
if (its_len >= 8 && ((*buf_64 == pattern && *o_buf_64 == o_pattern) ||
attr >= IS_FP_MOD)) {
u64 tmp_64 = *buf_64;
*buf_64 = repl;
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
#ifdef CMPLOG_COMBINE
if (*status == 1) { memcpy(cbuf + idx, buf_64, 8); }
#endif
*buf_64 = tmp_64;
// fprintf(stderr, "Status=%u\n", *status);
}
// reverse encoding
if (do_reverse && *status != 1) {
if (unlikely(cmp_extend_encoding(afl, h, SWAP64(pattern), SWAP64(repl),
SWAP64(o_pattern), SWAP64(changed_val),
attr, idx, taint_len, orig_buf, buf,
cbuf, len, 0, lvl, status))) {
return 1;
}
}
}
if (SHAPE_BYTES(h->shape) >= 4 && *status != 1) {
// if (its_len >= 4 && (attr <= 1 || attr >= 8))
// fprintf(stderr,
// "TestU32: %u>=4 (idx=%u attr=%u) %x==%x"
// " %x==%x <= %x<-%x\n",
// its_len, idx, attr, *buf_32, (u32)pattern, *o_buf_32,
// (u32)o_pattern, (u32)repl, (u32)changed_val);
if (its_len >= 4 &&
((*buf_32 == (u32)pattern && *o_buf_32 == (u32)o_pattern) ||
attr >= IS_FP_MOD)) {
u32 tmp_32 = *buf_32;
*buf_32 = (u32)repl;
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
#ifdef CMPLOG_COMBINE
if (*status == 1) { memcpy(cbuf + idx, buf_32, 4); }
#endif
*buf_32 = tmp_32;
// fprintf(stderr, "Status=%u\n", *status);
}
// reverse encoding
if (do_reverse && *status != 1) {
if (unlikely(cmp_extend_encoding(afl, h, SWAP32(pattern), SWAP32(repl),
SWAP32(o_pattern), SWAP32(changed_val),
attr, idx, taint_len, orig_buf, buf,
cbuf, len, 0, lvl, status))) {
return 1;
}
}
}
if (SHAPE_BYTES(h->shape) >= 2 && *status != 1) {
if (its_len >= 2 &&
((*buf_16 == (u16)pattern && *o_buf_16 == (u16)o_pattern) ||
attr >= IS_FP_MOD)) {
u16 tmp_16 = *buf_16;
*buf_16 = (u16)repl;
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
#ifdef CMPLOG_COMBINE
if (*status == 1) { memcpy(cbuf + idx, buf_16, 2); }
#endif
*buf_16 = tmp_16;
}
// reverse encoding
if (do_reverse && *status != 1) {
if (unlikely(cmp_extend_encoding(afl, h, SWAP16(pattern), SWAP16(repl),
SWAP16(o_pattern), SWAP16(changed_val),
attr, idx, taint_len, orig_buf, buf,
cbuf, len, 0, lvl, status))) {
return 1;
}
}
}
if (*status != 1) { // u8
// if (its_len >= 1)
// fprintf(stderr,
// "TestU8: %u>=1 (idx=%u attr=%u) %x==%x %x==%x <= %x<-%x\n",
// its_len, idx, attr, *buf_8, (u8)pattern, *o_buf_8,
// (u8)o_pattern, (u8)repl, (u8)changed_val);
if (its_len >= 1 &&
((*buf_8 == (u8)pattern && *o_buf_8 == (u8)o_pattern) ||
attr >= IS_FP_MOD)) {
u8 tmp_8 = *buf_8;
*buf_8 = (u8)repl;
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
#ifdef CMPLOG_COMBINE
if (*status == 1) { cbuf[idx] = *buf_8; }
#endif
*buf_8 = tmp_8;
}
}
}
// here we add and subract 1 from the value, but only if it is not an
// == or != comparison
// Bits: 1 = Equal, 2 = Greater, 4 = Lesser, 8 = Float
// 16 = modified float, 32 = modified integer (modified = wont match
// in original buffer)
//#ifdef CMPLOG_SOLVE_ARITHMETIC
if (!afl->cmplog_enable_arith || lvl < LVL3 || attr == IS_TRANSFORM) {
return 0;
}
if (!(attr & (IS_GREATER | IS_LESSER)) || SHAPE_BYTES(h->shape) < 4) {
return 0;
}
// transform >= to < and <= to >
if ((attr & IS_EQUAL) && (attr & (IS_GREATER | IS_LESSER))) {
if (attr & 2) {
attr += 2;
} else {
attr -= 2;
}
}
// lesser/greater FP comparison
if (attr >= IS_FP && attr < IS_FP_MOD) {
u64 repl_new;
if (attr & IS_GREATER) {
if (SHAPE_BYTES(h->shape) == 4 && its_len >= 4) {
float *f = (float *)&repl;
float g = *f;
g += 1.0;
u32 *r = (u32 *)&g;
repl_new = (u32)*r;
} else if (SHAPE_BYTES(h->shape) == 8 && its_len >= 8) {
double *f = (double *)&repl;
double g = *f;
g += 1.0;
u64 *r = (u64 *)&g;
repl_new = *r;
} else {
return 0;
}
changed_val = repl_new;
if (unlikely(cmp_extend_encoding(
afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx,
taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
return 1;
}
} else {
if (SHAPE_BYTES(h->shape) == 4) {
float *f = (float *)&repl;
float g = *f;
g -= 1.0;
u32 *r = (u32 *)&g;
repl_new = (u32)*r;
} else if (SHAPE_BYTES(h->shape) == 8) {
double *f = (double *)&repl;
double g = *f;
g -= 1.0;
u64 *r = (u64 *)&g;
repl_new = *r;
} else {
return 0;
}
changed_val = repl_new;
if (unlikely(cmp_extend_encoding(
afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx,
taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
return 1;
}
}
// transform double to float, llvm likes to do that internally ...
if (SHAPE_BYTES(h->shape) == 8 && its_len >= 4) {
double *f = (double *)&repl;
float g = (float)*f;
repl_new = 0;
#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
memcpy((char *)&repl_new, (char *)&g, 4);
#else
memcpy(((char *)&repl_new) + 4, (char *)&g, 4);
#endif
changed_val = repl_new;
h->shape = 3; // modify shape
// fprintf(stderr, "DOUBLE2FLOAT %llx\n", repl_new);
if (unlikely(cmp_extend_encoding(
afl, h, pattern, repl_new, o_pattern, changed_val, 16, idx,
taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
h->shape = 7; // recover shape
return 1;
}
h->shape = 7; // recover shape
}
}
else if (attr < IS_FP) {
// lesser/greater integer comparison
u64 repl_new;
if (attr & IS_GREATER) {
repl_new = repl + 1;
changed_val = repl_new;
if (unlikely(cmp_extend_encoding(
afl, h, pattern, repl_new, o_pattern, changed_val, 32, idx,
taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
return 1;
}
} else {
repl_new = repl - 1;
changed_val = repl_new;
if (unlikely(cmp_extend_encoding(
afl, h, pattern, repl_new, o_pattern, changed_val, 32, idx,
taint_len, orig_buf, buf, cbuf, len, 1, lvl, status))) {
return 1;
}
}
}
//#endif /*
// CMPLOG_SOLVE_ARITHMETIC
return 0;
}
#ifdef WORD_SIZE_64
static u8 cmp_extend_encodingN(afl_state_t *afl, struct cmp_header *h,
u128 pattern, u128 repl, u128 o_pattern,
u128 changed_val, u8 attr, u32 idx,
u32 taint_len, u8 *orig_buf, u8 *buf, u8 *cbuf,
u32 len, u8 do_reverse, u8 lvl, u8 *status) {
u8 *ptr = (u8 *)&buf[idx];
u8 *o_ptr = (u8 *)&orig_buf[idx];
u8 *p = (u8 *)&pattern;
u8 *o_p = (u8 *)&o_pattern;
u8 *r = (u8 *)&repl;
u8 backup[16];
u32 its_len = MIN(len - idx, taint_len);
u32 shape = h->shape + 1;
#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
size_t off = 0;
#else
size_t off = 16 - shape;
#endif
if (its_len >= shape) {
#ifdef _DEBUG
fprintf(stderr, "TestUN: %u>=%u (len=%u idx=%u attr=%u off=%lu) (%u) ",
its_len, shape, len, idx, attr, off, do_reverse);
u32 i;
u8 *o_r = (u8 *)&changed_val;
for (i = 0; i < shape; i++)
fprintf(stderr, "%02x", ptr[i]);
fprintf(stderr, "==");
for (i = 0; i < shape; i++)
fprintf(stderr, "%02x", p[off + i]);
fprintf(stderr, " ");
for (i = 0; i < shape; i++)
fprintf(stderr, "%02x", o_ptr[i]);
fprintf(stderr, "==");
for (i = 0; i < shape; i++)
fprintf(stderr, "%02x", o_p[off + i]);
fprintf(stderr, " <= ");
for (i = 0; i < shape; i++)
fprintf(stderr, "%02x", r[off + i]);
fprintf(stderr, "<-");
for (i = 0; i < shape; i++)
fprintf(stderr, "%02x", o_r[off + i]);
fprintf(stderr, "\n");
#endif
if (!memcmp(ptr, p + off, shape) && !memcmp(o_ptr, o_p + off, shape)) {
memcpy(backup, ptr, shape);
memcpy(ptr, r + off, shape);
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
#ifdef CMPLOG_COMBINE
if (*status == 1) { memcpy(cbuf + idx, r, shape); }
#endif
memcpy(ptr, backup, shape);
#ifdef _DEBUG
fprintf(stderr, "Status=%u\n", *status);
#endif
}
// reverse encoding
if (do_reverse && *status != 1) {
if (unlikely(cmp_extend_encodingN(
afl, h, SWAPN(pattern, (shape << 3)), SWAPN(repl, (shape << 3)),
SWAPN(o_pattern, (shape << 3)), SWAPN(changed_val, (shape << 3)),
attr, idx, taint_len, orig_buf, buf, cbuf, len, 0, lvl,
status))) {
return 1;
}
}
}
return 0;
}
#endif
static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) {
u8 *b = (u8 *)&v;
u32 k;
u8 cons_ff = 0, cons_0 = 0;
for (k = 0; k < shape; ++k) {
if (b[k] == 0) {
++cons_0;
} else if (b[k] == 0xff) {
++cons_ff;
} else {
cons_0 = cons_ff = 0;
}
if (cons_0 > 1 || cons_ff > 1) { return; }
}
maybe_add_auto(afl, (u8 *)&v, shape);
u64 rev;
switch (shape) {
case 1:
break;
case 2:
rev = SWAP16((u16)v);
maybe_add_auto(afl, (u8 *)&rev, shape);
break;
case 4:
rev = SWAP32((u32)v);
maybe_add_auto(afl, (u8 *)&rev, shape);
break;
case 8:
rev = SWAP64(v);
maybe_add_auto(afl, (u8 *)&rev, shape);
break;
}
}
#ifdef WORD_SIZE_64
static void try_to_add_to_dictN(afl_state_t *afl, u128 v, u8 size) {
u8 *b = (u8 *)&v;
u32 k;
u8 cons_ff = 0, cons_0 = 0;
#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
u32 off = 0;
for (k = 0; k < size; ++k) {
#else
u32 off = 16 - size;
for (k = 16 - size; k < 16; ++k) {
#endif
if (b[k] == 0) {
++cons_0;
} else if (b[k] == 0xff) {
++cons_ff;
} else {
cons_0 = cons_ff = 0;
}
}
maybe_add_auto(afl, (u8 *)&v + off, size);
u128 rev = SWAPN(v, size);
maybe_add_auto(afl, (u8 *)&rev + off, size);
}
#endif
#define SWAPA(_x) ((_x & 0xf8) + ((_x & 7) ^ 0x07))
static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
u32 len, u32 lvl, struct tainted *taint) {
struct cmp_header *h = &afl->shm.cmp_map->headers[key];
struct tainted * t;
u32 i, j, idx, taint_len, loggeds;
u32 have_taint = 1;
u8 status = 0, found_one = 0;
/* loop cmps are useless, detect and ignore them */
#ifdef WORD_SIZE_64
u32 is_n = 0;
u128 s128_v0 = 0, s128_v1 = 0, orig_s128_v0 = 0, orig_s128_v1 = 0;
#endif
u64 s_v0, s_v1;
u8 s_v0_fixed = 1, s_v1_fixed = 1;
u8 s_v0_inc = 1, s_v1_inc = 1;
u8 s_v0_dec = 1, s_v1_dec = 1;
if (h->hits > CMP_MAP_H) {
loggeds = CMP_MAP_H;
} else {
loggeds = h->hits;
}
#ifdef WORD_SIZE_64
switch (SHAPE_BYTES(h->shape)) {
case 1:
case 2:
case 4:
case 8:
break;
default:
is_n = 1;
}
#endif
for (i = 0; i < loggeds; ++i) {
struct cmp_operands *o = &afl->shm.cmp_map->log[key][i];
// loop detection code
if (i == 0) {
s_v0 = o->v0;
s_v1 = o->v1;
} else {
if (s_v0 != o->v0) { s_v0_fixed = 0; }
if (s_v1 != o->v1) { s_v1_fixed = 0; }
if (s_v0 + 1 != o->v0) { s_v0_inc = 0; }
if (s_v1 + 1 != o->v1) { s_v1_inc = 0; }
if (s_v0 - 1 != o->v0) { s_v0_dec = 0; }
if (s_v1 - 1 != o->v1) { s_v1_dec = 0; }
s_v0 = o->v0;
s_v1 = o->v1;
}
struct cmp_operands *orig_o = &afl->orig_cmp_map->log[key][i];
// opt not in the paper
for (j = 0; j < i; ++j) {
if (afl->shm.cmp_map->log[key][j].v0 == o->v0 &&
afl->shm.cmp_map->log[key][i].v1 == o->v1) {
goto cmp_fuzz_next_iter;
}
}
#ifdef _DEBUG
fprintf(stderr, "Handling: %llx->%llx vs %llx->%llx attr=%u shape=%u\n",
orig_o->v0, o->v0, orig_o->v1, o->v1, h->attribute,
SHAPE_BYTES(h->shape));
#endif
t = taint;
while (t->next) {
t = t->next;
}
#ifdef WORD_SIZE_64
if (unlikely(is_n)) {
s128_v0 = ((u128)o->v0) + (((u128)o->v0_128) << 64);
s128_v1 = ((u128)o->v1) + (((u128)o->v1_128) << 64);
orig_s128_v0 = ((u128)orig_o->v0) + (((u128)orig_o->v0_128) << 64);
orig_s128_v1 = ((u128)orig_o->v1) + (((u128)orig_o->v1_128) << 64);
}
#endif
for (idx = 0; idx < len; ++idx) {
if (have_taint) {
if (!t || idx < t->pos) {
continue;
} else {
taint_len = t->pos + t->len - idx;
if (idx == t->pos + t->len - 1) { t = t->prev; }
}
} else {
taint_len = len - idx;
}
status = 0;
#ifdef WORD_SIZE_64
if (is_n) { // _ExtInt special case including u128
if (s128_v0 != orig_s128_v0 && orig_s128_v0 != orig_s128_v1) {
if (unlikely(cmp_extend_encodingN(
afl, h, s128_v0, s128_v1, orig_s128_v0, orig_s128_v1,
h->attribute, idx, taint_len, orig_buf, buf, cbuf, len, 1,
lvl, &status))) {
return 1;
}
}
if (status == 1) {
found_one = 1;
break;
}
if (s128_v1 != orig_s128_v1 && orig_s128_v1 != orig_s128_v0) {
if (unlikely(cmp_extend_encodingN(
afl, h, s128_v1, s128_v0, orig_s128_v1, orig_s128_v0,
SWAPA(h->attribute), idx, taint_len, orig_buf, buf, cbuf, len,
1, lvl, &status))) {
return 1;
}
}
if (status == 1) {
found_one = 1;
break;
}
}
#endif
#ifdef _DEBUG
if (o->v0 != orig_o->v0 || o->v1 != orig_o->v1)
fprintf(stderr, "key=%u idx=%u o0=%llu v0=%llu o1=%llu v1=%llu\n", key,
idx, orig_o->v0, o->v0, orig_o->v1, o->v1);
#endif
// even for u128 and _ExtInt we do cmp_extend_encoding() because
// if we got here their own special trials failed and it might just be
// a cast from e.g. u64 to u128 from the input data.
if ((o->v0 != orig_o->v0 || lvl >= LVL3) && orig_o->v0 != orig_o->v1) {
if (unlikely(cmp_extend_encoding(
afl, h, o->v0, o->v1, orig_o->v0, orig_o->v1, h->attribute, idx,
taint_len, orig_buf, buf, cbuf, len, 1, lvl, &status))) {
return 1;
}
}
if (status == 1) {
found_one = 1;
break;
}
status = 0;
if ((o->v1 != orig_o->v1 || lvl >= LVL3) && orig_o->v0 != orig_o->v1) {
if (unlikely(cmp_extend_encoding(afl, h, o->v1, o->v0, orig_o->v1,
orig_o->v0, SWAPA(h->attribute), idx,
taint_len, orig_buf, buf, cbuf, len, 1,
lvl, &status))) {
return 1;
}
}
if (status == 1) {
found_one = 1;
break;
}
}
#ifdef _DEBUG
fprintf(stderr,
"END: %llx->%llx vs %llx->%llx attr=%u i=%u found=%u "
"isN=%u size=%u\n",
orig_o->v0, o->v0, orig_o->v1, o->v1, h->attribute, i, found_one,
is_n, SHAPE_BYTES(h->shape));
#endif
// If failed, add to dictionary
if (!found_one) {
if (afl->pass_stats[key].total == 0) {
#ifdef WORD_SIZE_64
if (unlikely(is_n)) {
try_to_add_to_dictN(afl, s128_v0, SHAPE_BYTES(h->shape));
try_to_add_to_dictN(afl, s128_v1, SHAPE_BYTES(h->shape));
} else
#endif
{
try_to_add_to_dict(afl, o->v0, SHAPE_BYTES(h->shape));
try_to_add_to_dict(afl, o->v1, SHAPE_BYTES(h->shape));
}
}
}
cmp_fuzz_next_iter:
afl->stage_cur++;
}
if (loggeds > 3 && ((s_v0_fixed && s_v1_inc) || (s_v1_fixed && s_v0_inc) ||
(s_v0_fixed && s_v1_dec) || (s_v1_fixed && s_v0_dec))) {
afl->pass_stats[key].total = afl->pass_stats[key].faileds = 0xff;
}
if (!found_one && afl->pass_stats[key].faileds < 0xff) {
afl->pass_stats[key].faileds++;
}
if (afl->pass_stats[key].total < 0xff) { afl->pass_stats[key].total++; }
return 0;
}
static u8 rtn_extend_encoding(afl_state_t *afl, u8 *pattern, u8 *repl,
u8 *o_pattern, u8 *changed_val, u8 plen, u32 idx,
u32 taint_len, u8 *orig_buf, u8 *buf, u8 *cbuf,
u32 len, u8 lvl, u8 *status) {
#ifndef CMPLOG_COMBINE
(void)(cbuf);
#endif
//#ifndef CMPLOG_SOLVE_TRANSFORM
// (void)(changed_val);
//#endif
u8 save[40];
u32 saved_idx = idx, pre, from = 0, to = 0, i, j;
u32 its_len = MIN((u32)plen, len - idx);
its_len = MIN(its_len, taint_len);
u32 saved_its_len = its_len;
if (lvl & LVL3) {
u32 max_to = MIN(4U, idx);
if (!(lvl & LVL1) && max_to) { from = 1; }
to = max_to;
}
memcpy(save, &buf[saved_idx - to], its_len + to);
(void)(j);
#ifdef _DEBUG
fprintf(stderr, "RTN T idx=%u lvl=%02x ", idx, lvl);
for (j = 0; j < 8; j++)
fprintf(stderr, "%02x", orig_buf[idx + j]);
fprintf(stderr, " -> ");
for (j = 0; j < 8; j++)
fprintf(stderr, "%02x", o_pattern[j]);
fprintf(stderr, " <= ");
for (j = 0; j < 8; j++)
fprintf(stderr, "%02x", repl[j]);
fprintf(stderr, "\n");
fprintf(stderr, " ");
for (j = 0; j < 8; j++)
fprintf(stderr, "%02x", buf[idx + j]);
fprintf(stderr, " -> ");
for (j = 0; j < 8; j++)
fprintf(stderr, "%02x", pattern[j]);
fprintf(stderr, " <= ");
for (j = 0; j < 8; j++)
fprintf(stderr, "%02x", changed_val[j]);
fprintf(stderr, "\n");
#endif
// Try to match the replace value up to 4 bytes before the current idx.
// This allows matching of eg.:
// if (memcmp(user_val, "TEST") == 0)
// if (memcmp(user_val, "TEST-VALUE") == 0) ...
// We only do this in lvl 3, otherwise we only do direct matching
for (pre = from; pre <= to; pre++) {
if (*status != 1 && (!pre || !memcmp(buf + saved_idx - pre, repl, pre))) {
idx = saved_idx - pre;
its_len = saved_its_len + pre;
for (i = 0; i < its_len; ++i) {
if ((pattern[i] != buf[idx + i] && o_pattern[i] != orig_buf[idx + i]) ||
*status == 1) {
break;
}
buf[idx + i] = repl[i];
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
#ifdef CMPLOG_COMBINE
if (*status == 1) { memcpy(cbuf + idx, &buf[idx], i); }
#endif
}
memcpy(&buf[idx], save + to - pre, i);
}
}
//#ifdef CMPLOG_SOLVE_TRANSFORM
if (*status == 1) return 0;
if (afl->cmplog_enable_transform && (lvl & LVL3)) {
u32 toupper = 0, tolower = 0, xor = 0, arith = 0, tohex = 0, fromhex = 0;
#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
u32 tob64 = 0, fromb64 = 0;
#endif
u32 from_0 = 0, from_x = 0, from_X = 0, from_slash = 0, from_up = 0;
u32 to_0 = 0, to_x = 0, to_slash = 0, to_up = 0;
u8 xor_val[32], arith_val[32], tmp[48];
idx = saved_idx;
its_len = saved_its_len;
memcpy(save, &buf[idx], its_len);
for (i = 0; i < its_len; ++i) {
xor_val[i] = pattern[i] ^ buf[idx + i];
arith_val[i] = pattern[i] - buf[idx + i];
if (i == 0) {
if (orig_buf[idx] == '0') {
from_0 = 1;
} else if (orig_buf[idx] == '\\') {
from_slash = 1;
}
if (repl[0] == '0') {
to_0 = 1;
} else if (repl[0] == '\\') {
to_slash = 1;
}
} else if (i == 1) {
if (orig_buf[idx + 1] == 'x') {
from_x = 1;
} else if (orig_buf[idx + 1] == 'X') {
from_X = from_x = 1;
}
if (repl[1] == 'x' || repl[1] == 'X') { to_x = 1; }
}
if (i < 16 && is_hex(repl + (i << 1))) {
++tohex;
if (!to_up) {
if (repl[i << 1] >= 'A' && repl[i << 1] <= 'F')
to_up = 1;
else if (repl[i << 1] >= 'a' && repl[i << 1] <= 'f')
to_up = 2;
if (repl[(i << 1) + 1] >= 'A' && repl[(i << 1) + 1] <= 'F')
to_up = 1;
else if (repl[(i << 1) + 1] >= 'a' && repl[(i << 1) + 1] <= 'f')
to_up = 2;
}
}
if ((i % 2)) {
if (len > idx + i && is_hex(orig_buf + idx + i)) {
fromhex += 2;
if (!from_up) {
if (orig_buf[idx + i] >= 'A' && orig_buf[idx + i] <= 'F')
from_up = 1;
else if (orig_buf[idx + i] >= 'a' && orig_buf[idx + i] <= 'f')
from_up = 2;
if (orig_buf[idx + i - 1] >= 'A' && orig_buf[idx + i - 1] <= 'F')
from_up = 1;
else if (orig_buf[idx + i - 1] >= 'a' &&
orig_buf[idx + i - 1] <= 'f')
from_up = 2;
}
}
}
#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
if (i % 3 == 2 && i < 24) {
if (is_base64(repl + ((i / 3) << 2))) tob64 += 3;
}
if (i % 4 == 3 && i < 24) {
if (is_base64(orig_buf + idx + i - 3)) fromb64 += 4;
}
#endif
if ((o_pattern[i] ^ orig_buf[idx + i]) == xor_val[i] && xor_val[i]) {
++xor;
}
if ((o_pattern[i] - orig_buf[idx + i]) == arith_val[i] && arith_val[i]) {
++arith;
}
if ((buf[idx + i] | 0x20) == pattern[i] &&
(orig_buf[idx + i] | 0x20) == o_pattern[i]) {
++tolower;
}
if ((buf[idx + i] & 0x5a) == pattern[i] &&
(orig_buf[idx + i] & 0x5a) == o_pattern[i]) {
++toupper;
}
#ifdef _DEBUG
fprintf(stderr,
"RTN idx=%u loop=%u xor=%u arith=%u tolower=%u toupper=%u "
"tohex=%u fromhex=%u to_0=%u to_slash=%u to_x=%u "
"from_0=%u from_slash=%u from_x=%u\n",
idx, i, xor, arith, tolower, toupper, tohex, fromhex, to_0,
to_slash, to_x, from_0, from_slash, from_x);
#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
fprintf(stderr, "RTN idx=%u loop=%u tob64=%u from64=%u\n", tob64,
fromb64);
#endif
#endif
#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
// input is base64 and converted to binary? convert repl to base64!
if ((i % 4) == 3 && i < 24 && fromb64 > i) {
to_base64(repl, tmp, i + 1);
memcpy(buf + idx, tmp, i + 1);
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
// fprintf(stderr, "RTN ATTEMPT fromb64 %u result %u\n", fromb64,
// *status);
}
// input is converted to base64? decode repl with base64!
if ((i % 3) == 2 && i < 24 && tob64 > i) {
u32 olen = from_base64(repl, tmp, i + 1);
memcpy(buf + idx, tmp, olen);
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
// fprintf(stderr, "RTN ATTEMPT tob64 %u idx=%u result %u\n", tob64,
// idx, *status);
}
#endif
// input is converted to hex? convert repl to binary!
if (i < 16 && tohex > i) {
u32 off;
if (to_slash + to_x + to_0 == 2) {
off = 2;
} else {
off = 0;
}
for (j = 0; j <= i; j++)
tmp[j] = (hex_table[repl[off + (j << 1)] - '0'] << 4) +
hex_table[repl[off + (j << 1) + 1] - '0'];
memcpy(buf + idx, tmp, i + 1);
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
// fprintf(stderr, "RTN ATTEMPT tohex %u result %u\n", tohex,
// *status);
}
// input is hex and converted to binary? convert repl to hex!
if (i && (i % 2) && i < 16 && fromhex &&
fromhex + from_slash + from_x + from_0 > i) {
u8 off = 0;
if (from_slash && from_x) {
tmp[0] = '\\';
if (from_X) {
tmp[1] = 'X';
} else {
tmp[1] = 'x';
}
off = 2;
} else if (from_0 && from_x) {
tmp[0] = '0';
if (from_X) {
tmp[1] = 'X';
} else {
tmp[1] = 'x';
}
off = 2;
}
if (to_up == 1) {
for (j = 0; j <= (i >> 1); j++) {
tmp[off + (j << 1)] = hex_table_up[repl[j] >> 4];
tmp[off + (j << 1) + 1] = hex_table_up[repl[j] % 16];
}
} else {
for (j = 0; j <= (i >> 1); j++) {
tmp[off + (j << 1)] = hex_table_low[repl[j] >> 4];
tmp[off + (j << 1) + 1] = hex_table_low[repl[j] % 16];
}
}
memcpy(buf + idx, tmp, i + 1 + off);
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
// fprintf(stderr, "RTN ATTEMPT fromhex %u result %u\n", fromhex,
// *status);
memcpy(buf + idx + i, save + i, i + 1 + off);
}
if (xor > i) {
for (j = 0; j <= i; j++)
buf[idx + j] = repl[j] ^ xor_val[j];
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
// fprintf(stderr, "RTN ATTEMPT xor %u result %u\n", xor, *status);
}
if (arith > i && *status != 1) {
for (j = 0; j <= i; j++)
buf[idx + j] = repl[j] - arith_val[j];
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
// fprintf(stderr, "RTN ATTEMPT arith %u result %u\n", arith,
// *status);
}
if (toupper > i && *status != 1) {
for (j = 0; j <= i; j++)
buf[idx + j] = repl[j] | 0x20;
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
// fprintf(stderr, "RTN ATTEMPT toupper %u result %u\n", toupper,
// *status);
}
if (tolower > i && *status != 1) {
for (j = 0; j <= i; j++)
buf[idx + j] = repl[j] & 0x5f;
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
// fprintf(stderr, "RTN ATTEMPT tolower %u result %u\n", tolower,
// *status);
}
#ifdef CMPLOG_COMBINE
if (*status == 1) { memcpy(cbuf + idx, &buf[idx], i + 1); }
#endif
if ((i >= 7 &&
(i >= xor&&i >= arith &&i >= tolower &&i >= toupper &&i > tohex &&i >
(fromhex + from_0 + from_x + from_slash + 1)
#ifdef CMPLOG_SOLVE_TRANSFORM_BASE64
&& i > tob64 + 3 && i > fromb64 + 4
#endif
)) ||
repl[i] != changed_val[i] || *status == 1) {
break;
}
}
memcpy(&buf[idx], save, i);
}
//#endif
return 0;
}
static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
u32 len, u8 lvl, struct tainted *taint) {
struct tainted * t;
struct cmp_header *h = &afl->shm.cmp_map->headers[key];
u32 i, j, idx, have_taint = 1, taint_len, loggeds;
u8 status = 0, found_one = 0;
if (h->hits > CMP_MAP_RTN_H) {
loggeds = CMP_MAP_RTN_H;
} else {
loggeds = h->hits;
}
for (i = 0; i < loggeds; ++i) {
struct cmpfn_operands *o =
&((struct cmpfn_operands *)afl->shm.cmp_map->log[key])[i];
struct cmpfn_operands *orig_o =
&((struct cmpfn_operands *)afl->orig_cmp_map->log[key])[i];
// opt not in the paper
for (j = 0; j < i; ++j) {
if (!memcmp(&((struct cmpfn_operands *)afl->shm.cmp_map->log[key])[j], o,
sizeof(struct cmpfn_operands))) {
goto rtn_fuzz_next_iter;
}
}
/*
struct cmp_header *hh = &afl->orig_cmp_map->headers[key];
fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits,
h->id, h->shape, h->attribute);
for (j = 0; j < 8; j++) fprintf(stderr, "%02x", o->v0[j]);
fprintf(stderr, " v1=");
for (j = 0; j < 8; j++) fprintf(stderr, "%02x", o->v1[j]);
fprintf(stderr, "\nRTN O hits=%u id=%u shape=%u attr=%u o0=",
hh->hits, hh->id, hh->shape, hh->attribute);
for (j = 0; j < 8; j++) fprintf(stderr, "%02x", orig_o->v0[j]);
fprintf(stderr, " o1=");
for (j = 0; j < 8; j++) fprintf(stderr, "%02x", orig_o->v1[j]);
fprintf(stderr, "\n");
*/
t = taint;
while (t->next) {
t = t->next;
}
for (idx = 0; idx < len; ++idx) {
if (have_taint) {
if (!t || idx < t->pos) {
continue;
} else {
taint_len = t->pos + t->len - idx;
if (idx == t->pos + t->len - 1) { t = t->prev; }
}
} else {
taint_len = len - idx;
}
status = 0;
#ifdef _DEBUG
int w;
fprintf(stderr, "key=%u idx=%u len=%u o0=", key, idx,
SHAPE_BYTES(h->shape));
for (w = 0; w < SHAPE_BYTES(h->shape); ++w)
fprintf(stderr, "%02x", orig_o->v0[w]);
fprintf(stderr, " v0=");
for (w = 0; w < SHAPE_BYTES(h->shape); ++w)
fprintf(stderr, "%02x", o->v0[w]);
fprintf(stderr, " o1=");
for (w = 0; w < SHAPE_BYTES(h->shape); ++w)
fprintf(stderr, "%02x", orig_o->v1[w]);
fprintf(stderr, " v1=");
for (w = 0; w < SHAPE_BYTES(h->shape); ++w)
fprintf(stderr, "%02x", o->v1[w]);
fprintf(stderr, "\n");
#endif
if (unlikely(rtn_extend_encoding(
afl, o->v0, o->v1, orig_o->v0, orig_o->v1, SHAPE_BYTES(h->shape),
idx, taint_len, orig_buf, buf, cbuf, len, lvl, &status))) {
return 1;
}
if (status == 1) {
found_one = 1;
break;
}
status = 0;
if (unlikely(rtn_extend_encoding(
afl, o->v1, o->v0, orig_o->v1, orig_o->v0, SHAPE_BYTES(h->shape),
idx, taint_len, orig_buf, buf, cbuf, len, lvl, &status))) {
return 1;
}
if (status == 1) {
found_one = 1;
break;
}
}
// If failed, add to dictionary
if (!found_one && (lvl & LVL1)) {
if (unlikely(!afl->pass_stats[key].total)) {
maybe_add_auto(afl, o->v0, SHAPE_BYTES(h->shape));
maybe_add_auto(afl, o->v1, SHAPE_BYTES(h->shape));
}
}
rtn_fuzz_next_iter:
afl->stage_cur++;
}
if (!found_one && afl->pass_stats[key].faileds < 0xff) {
afl->pass_stats[key].faileds++;
}
if (afl->pass_stats[key].total < 0xff) { afl->pass_stats[key].total++; }
return 0;
}
///// Input to State stage
// afl->queue_cur->exec_cksum
u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
u8 r = 1;
if (unlikely(!afl->pass_stats)) {
afl->pass_stats = ck_alloc(sizeof(struct afl_pass_stat) * CMP_MAP_W);
}
struct tainted *taint = NULL;
if (!afl->queue_cur->taint || !afl->queue_cur->cmplog_colorinput) {
if (unlikely(colorization(afl, buf, len, &taint))) { return 1; }
// no taint? still try, create a dummy to prevent again colorization
if (!taint) {
#ifdef _DEBUG
fprintf(stderr, "TAINT FAILED\n");
#endif
afl->queue_cur->colorized = CMPLOG_LVL_MAX;
return 0;
}
#ifdef _DEBUG
else if (taint->pos == 0 && taint->len == len) {
fprintf(stderr, "TAINT FULL\n");
}
#endif
} else {
buf = afl->queue_cur->cmplog_colorinput;
taint = afl->queue_cur->taint;
}
struct tainted *t = taint;
while (t) {
#ifdef _DEBUG
fprintf(stderr, "T: idx=%u len=%u\n", t->pos, t->len);
#endif
t = t->next;
}
#if defined(_DEBUG) || defined(CMPLOG_INTROSPECTION)
u64 start_time = get_cur_time();
u32 cmp_locations = 0;
#endif
// Generate the cmplog data
// manually clear the full cmp_map
memset(afl->shm.cmp_map, 0, sizeof(struct cmp_map));
if (unlikely(common_fuzz_cmplog_stuff(afl, orig_buf, len))) {
afl->queue_cur->colorized = CMPLOG_LVL_MAX;
while (taint) {
t = taint->next;
ck_free(taint);
taint = t;
}
return 1;
}
if (unlikely(!afl->orig_cmp_map)) {
afl->orig_cmp_map = ck_alloc_nozero(sizeof(struct cmp_map));
}
memcpy(afl->orig_cmp_map, afl->shm.cmp_map, sizeof(struct cmp_map));
memset(afl->shm.cmp_map->headers, 0, sizeof(struct cmp_header) * CMP_MAP_W);
if (unlikely(common_fuzz_cmplog_stuff(afl, buf, len))) {
afl->queue_cur->colorized = CMPLOG_LVL_MAX;
while (taint) {
t = taint->next;
ck_free(taint);
taint = t;
}
return 1;
}
#ifdef _DEBUG
dump("ORIG", orig_buf, len);
dump("NEW ", buf, len);
#endif
// Start insertion loop
u64 orig_hit_cnt, new_hit_cnt;
u64 orig_execs = afl->fsrv.total_execs;
orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
u64 screen_update = 100000 / afl->queue_cur->exec_us,
execs = afl->fsrv.total_execs;
afl->stage_name = "input-to-state";
afl->stage_short = "its";
afl->stage_max = 0;
afl->stage_cur = 0;
u32 lvl = (afl->queue_cur->colorized ? 0 : LVL1) +
(afl->cmplog_lvl == CMPLOG_LVL_MAX ? LVL3 : 0);
#ifdef CMPLOG_COMBINE
u8 *cbuf = afl_realloc((void **)&afl->in_scratch_buf, len + 128);
memcpy(cbuf, orig_buf, len);
u8 *virgin_backup = afl_realloc((void **)&afl->ex_buf, afl->shm.map_size);
memcpy(virgin_backup, afl->virgin_bits, afl->shm.map_size);
#else
u8 *cbuf = NULL;
#endif
u32 k;
for (k = 0; k < CMP_MAP_W; ++k) {
if (!afl->shm.cmp_map->headers[k].hits) { continue; }
if (afl->pass_stats[k].faileds >= CMPLOG_FAIL_MAX ||
afl->pass_stats[k].total >= CMPLOG_FAIL_MAX) {
#ifdef _DEBUG
fprintf(stderr, "DISABLED %u\n", k);
#endif
afl->shm.cmp_map->headers[k].hits = 0; // ignore this cmp
}
if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS) {
afl->stage_max +=
MIN((u32)(afl->shm.cmp_map->headers[k].hits), (u32)CMP_MAP_H);
} else {
afl->stage_max +=
MIN((u32)(afl->shm.cmp_map->headers[k].hits), (u32)CMP_MAP_RTN_H);
}
}
for (k = 0; k < CMP_MAP_W; ++k) {
if (!afl->shm.cmp_map->headers[k].hits) { continue; }
#if defined(_DEBUG) || defined(CMPLOG_INTROSPECTION)
++cmp_locations;
#endif
if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS) {
if (unlikely(cmp_fuzz(afl, k, orig_buf, buf, cbuf, len, lvl, taint))) {
goto exit_its;
}
} else if ((lvl & LVL1)
//#ifdef CMPLOG_SOLVE_TRANSFORM
|| ((lvl & LVL3) && afl->cmplog_enable_transform)
//#endif
) {
if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, cbuf, len, lvl, taint))) {
goto exit_its;
}
}
if (afl->fsrv.total_execs - execs > screen_update) {
execs = afl->fsrv.total_execs;
show_stats(afl);
}
}
r = 0;
exit_its:
if (afl->cmplog_lvl == CMPLOG_LVL_MAX) {
afl->queue_cur->colorized = CMPLOG_LVL_MAX;
if (afl->queue_cur->cmplog_colorinput) {
ck_free(afl->queue_cur->cmplog_colorinput);
}
while (taint) {
t = taint->next;
ck_free(taint);
taint = t;
}
afl->queue_cur->taint = NULL;
} else {
afl->queue_cur->colorized = LVL2;
if (!afl->queue_cur->taint) { afl->queue_cur->taint = taint; }
if (!afl->queue_cur->cmplog_colorinput) {
afl->queue_cur->cmplog_colorinput = ck_alloc_nozero(len);
memcpy(afl->queue_cur->cmplog_colorinput, buf, len);
memcpy(buf, orig_buf, len);
}
}
#ifdef CMPLOG_COMBINE
if (afl->queued_paths + afl->unique_crashes > orig_hit_cnt + 1) {
// copy the current virgin bits so we can recover the information
u8 *virgin_save = afl_realloc((void **)&afl->eff_buf, afl->shm.map_size);
memcpy(virgin_save, afl->virgin_bits, afl->shm.map_size);
// reset virgin bits to the backup previous to redqueen
memcpy(afl->virgin_bits, virgin_backup, afl->shm.map_size);
u8 status = 0;
its_fuzz(afl, cbuf, len, &status);
// now combine with the saved virgin bits
#ifdef WORD_SIZE_64
u64 *v = (u64 *)afl->virgin_bits;
u64 *s = (u64 *)virgin_save;
u32 i;
for (i = 0; i < (afl->shm.map_size >> 3); i++) {
v[i] &= s[i];
}
#else
u32 *v = (u32 *)afl->virgin_bits;
u32 *s = (u32 *)virgin_save;
u32 i;
for (i = 0; i < (afl->shm.map_size >> 2); i++) {
v[i] &= s[i];
}
#endif
#ifdef _DEBUG
dump("COMB", cbuf, len);
if (status == 1) {
fprintf(stderr, "NEW CMPLOG_COMBINED\n");
} else {
fprintf(stderr, "NO new combined\n");
}
#endif
}
#endif
new_hit_cnt = afl->queued_paths + afl->unique_crashes;
afl->stage_finds[STAGE_ITS] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_ITS] += afl->fsrv.total_execs - orig_execs;
#if defined(_DEBUG) || defined(CMPLOG_INTROSPECTION)
FILE *f = stderr;
#ifndef _DEBUG
if (afl->not_on_tty) {
char fn[4096];
snprintf(fn, sizeof(fn), "%s/introspection_cmplog.txt", afl->out_dir);
f = fopen(fn, "a");
}
#endif
if (f) {
fprintf(f,
"Cmplog: fname=%s len=%u ms=%llu result=%u finds=%llu entries=%u\n",
afl->queue_cur->fname, len, get_cur_time() - start_time, r,
new_hit_cnt - orig_hit_cnt, cmp_locations);
#ifndef _DEBUG
if (afl->not_on_tty) { fclose(f); }
#endif
}
#endif
return r;
}