Compare commits

...

212 Commits

Author SHA1 Message Date
5a2688c213 fi 2024-06-05 10:34:24 +02:00
c31817863b ensure model.bin 2024-06-05 10:12:45 +02:00
54684728a1 fix 2024-06-05 10:00:46 +02:00
4c8e473376 get libxgboost 2024-06-05 09:50:53 +02:00
f1d829c7ca xgbooster 2024-06-04 16:15:39 +02:00
c900a8e30c model.bin 2024-06-04 13:45:25 +02:00
fd82e3330c add model 2024-06-04 13:45:17 +02:00
1db82f3303 update grammar mutator 2024-06-03 09:23:43 +02:00
2d4a4ba73f fix afl-showmap 2024-06-01 16:55:56 +02:00
ca55858aa7 Merge pull request #2107 from AFLplusplus/reg
fix regression
2024-06-01 16:34:50 +02:00
e639521b01 changelog 2024-06-01 16:34:23 +02:00
894339c5d7 try regression fix 2024-06-01 12:26:26 +02:00
e13dc9b7e6 todo 2024-06-01 12:17:53 +02:00
9419e39fdf nits 2024-05-31 18:32:31 +02:00
a3125c38f4 fix afl-showmap shmmemleak 2024-05-29 12:55:28 +02:00
224add0222 update unicorn 2024-05-28 11:12:33 +02:00
19636f748c Unicornafl: Fix incorrect comment (#2103) 2024-05-28 02:24:43 +02:00
7aa5e1c443 Merge pull request #2104 from Evian-Zhang/fix-unicorn-lldb-dumper
Make lldb dumper of unicorn_mode work in modern LLDB
2024-05-27 21:18:28 +02:00
93279db71b Make lldb dumper of unicorn_mode work in modern LLDB 2024-05-27 19:15:35 +08:00
5bf760510e Merge pull request #2102 from ndrewh/testcache-fix
fix: testcache hangs for large test cases
2024-05-26 08:12:29 +02:00
03dc80afc4 fix: testcache hangs for large test cases 2024-05-25 23:44:57 +00:00
fda3106fd9 Merge pull request #2099 from Atlante45/dev
Fix dynamic_lookup linker flag for Apple clang
2024-05-24 01:33:55 +02:00
9721a77204 Fix dynamic_lookup linker flag for Apple clang 2024-05-23 11:14:53 -07:00
92a8c2804f fix the fix for symcc 2024-05-21 16:31:42 +02:00
e1521fa8eb fix symcc custom mutator 2024-05-21 11:04:25 +02:00
4e3cd8ac3f nit 2024-05-20 14:02:22 +02:00
31a8beb449 support new llvm 19 changes 2024-05-19 13:47:53 +02:00
e7d871c8bf Merge pull request #2093 from AFLplusplus/dev
push to stable
2024-05-17 23:55:55 +02:00
56d5aa3101 log 2024-05-17 23:55:43 +02:00
c6a2a4046e Merge pull request #2092 from fbeqv/dev
Fix runtime underflow & -V exiting before syncing
2024-05-17 23:41:39 +02:00
6dd5e931fc Fix runtime underflow & -V exiting before syncing
print_stats sets exit_soon even while syncing, this leaves -V 0 still broken, as we don't finish syncing.

Additionally, the change that introduced the previous -V fix also broke the runtime tracking, as runtime needs to include all time including sync, splice etc. This caused an underflow in the reported runtime.
2024-05-17 14:33:32 -07:00
635140ba43 help qemu build for some linux platforms 2024-05-17 09:45:56 +02:00
497f341eac Revert "no weights"
This reverts commit 068aa13c6b.
2024-05-16 14:27:33 +02:00
068aa13c6b no weights 2024-05-16 14:27:04 +02:00
ba7ae6c59d nits 2024-05-16 14:21:00 +02:00
6ae95271be nits 2024-05-16 09:17:59 +02:00
a2e0163cc1 Merge pull request #2091 from bet4it/collect_coverage
Fix bug of `afl-showmap` in `collect_coverage` mode
2024-05-16 09:14:15 +02:00
1db3b81d2e dump cc 2024-05-15 14:16:44 +02:00
0a16ea7487 better cmplog ci test for low memory machines 2024-05-15 10:57:46 +02:00
a26bb0b0f2 Merge pull request #2090 from AFLplusplus/dev
push to stable
2024-05-14 13:18:22 +02:00
7d3530a22e nit 2024-05-14 13:07:47 +02:00
a87ea96913 make slow systems pass our test suite 2024-05-14 12:58:45 +02:00
81609a0f42 Merge pull request #2089 from nj00001/dev
Fix afl-fuzz -G option not configuring maximum input data size for nyx
2024-05-14 12:48:16 +02:00
938edab25f consider llvm 18 stable 2024-05-14 12:45:09 +02:00
29c9870658 disable xml/curl/g_ string transform compare 2024-05-14 12:35:32 +02:00
b6c4f3775a disable xml/curl/g_ string transform compare 2024-05-14 12:34:51 +02:00
5ee5564ae2 backup afl->max_length to afl->fsrv.max_length 2024-05-14 18:28:18 +08:00
ab36756061 change MAX_FILE to fsrv->max_length 2024-05-14 18:27:12 +08:00
831b8f35d5 Keep a backup of max_length in the afl_forkserver_t structure 2024-05-14 18:23:53 +08:00
0cf78b7748 Fix bug of afl-showmap in collect_coverage mode 2024-05-14 17:17:58 +08:00
0892a2245e float laf check 2024-05-13 20:28:50 +02:00
622474e9e4 disable -> no variants 2024-05-13 19:51:38 +02:00
0cabc12f91 Merge pull request #2086 from smoelius/dev
Add `AFL_SHA1_FILENAMES` option
2024-05-13 19:32:44 +02:00
b282ce999d post_process after trim 2024-05-13 13:42:58 +02:00
24b9d74e70 compcov int fix 2024-05-13 08:44:43 +02:00
c03f2897d0 Add AFL_SHA1_FILENAMES option 2024-05-12 05:44:14 -04:00
90fbf59bf1 Merge pull request #2084 from AFLplusplus/dev
push to stable
2024-05-11 09:16:21 +02:00
93c7cbd496 update unicorn 2024-05-11 09:01:33 +02:00
db60555c1b update changelog 2024-05-11 08:59:01 +02:00
45117a3384 Merge pull request #2083 from elboulangero/i386
Re-enable i386
2024-05-11 08:55:59 +02:00
4d4880b428 afl-cc: Re-enable i386
Was disabled in 136febaf68

Closes: #2081
2024-05-11 00:48:04 +07:00
ac6ccd53df stat update during syncing 2024-05-07 16:46:24 +02:00
4ec376bd6a Merge pull request #2076 from louismerlin/fix-whatsup-time
Fix `afl_whatsup` findings timer
2024-05-02 17:30:59 +02:00
3c0448305b Guard /proc/uptime cat with a uname check 2024-05-02 17:19:37 +02:00
a6029a10cc Fix CUR_TIME computation 2024-05-02 16:12:50 +02:00
26eaf53a83 AFL_DISABLE_REDUNDANT 2024-05-02 08:35:24 +02:00
5d623a27ed try enhanced asan support 2024-04-30 11:59:49 +02:00
69e554b941 Merge pull request #2074 from Kiprey/patch-2
Fix wrong warning in SanitizerCoverageLTO.so.cc
2024-04-29 17:11:41 +02:00
7340374a7c Fix wrong warning in SanitizerCoverageLTO.so.cc 2024-04-29 16:14:49 +08:00
67d356b73f update qemuafl 2024-04-28 15:41:24 +02:00
da18f1f722 Merge pull request #2073 from Acture/dev
Fix: Removed the redundant `id` field from redqueen.c
2024-04-28 15:39:32 +02:00
58abcceff5 Bug fix: Removed the redundant id field from the debug output in the afl-fuzz-redqueen.c file since cmp_header no longer have this field. 2024-04-28 16:24:52 +08:00
ad0d0c77fb Merge pull request #2071 from AFLplusplus/dev
Push to stable
2024-04-26 16:17:41 +02:00
2c3f761ede changes 2024-04-26 16:16:21 +02:00
70c60cfba7 work with spaces in filenames 2024-04-26 16:14:50 +02:00
f3b6d64ad3 Merge pull request #2066 from ahuo1/dev
fix: initialize n_fuzz_entry in perform_dry_run.
2024-04-26 09:44:49 +02:00
43e9a13921 add schedule check. 2024-04-26 07:45:58 +08:00
526dbe8f16 fix: initialize n_fuzz_entry in perform_dry_run. 2024-04-25 21:28:58 +08:00
951a0e5225 fix AFL_PERSISTENT_RECORD 2024-04-25 10:04:58 +02:00
458b939bc4 LTO fix 2024-04-19 17:34:50 +02:00
476aca5b67 nits 2024-04-19 15:45:00 +02:00
96bf0f8323 Merge pull request #2061 from jschwartzentruber/change_smm_vis
Specify shared memory visibility
2024-04-18 17:30:51 +02:00
58206a3180 Set explicit visibility on shared memory variables. 2024-04-17 14:40:41 -04:00
f138ab8ac6 Merge pull request #2059 from elboulangero/afl-gcc
Fix afl-gcc
2024-04-17 12:55:34 +02:00
50839cf6e9 afl-cc: Complete fix for afl-as
Look for afl-as, and then make sure that there's a 'as' binary in the
same directory, that seems to be either a symlink to, or a copy of,
afl-as.
2024-04-17 16:41:03 +07:00
626a4434ed afl-cc: Use afl-as (rather than as) to find obj path 2024-04-17 16:40:58 +07:00
d84cc73d13 afl-cc: Add missing debug statement
For each path that is tried, there's a debug log printed, _except_ for
this one. Fix it.
2024-04-17 16:40:55 +07:00
6b049536f1 v4.21 init 2024-04-13 11:54:08 +02:00
1d17210d9f Merge pull request #2052 from AFLplusplus/dev
4.20 release pre-PR
2024-04-13 11:50:49 +02:00
1582aa9da2 Merge pull request #2027 from choller/nyx-handler-fix
Add optional handling of Nyx InvalidWriteToPayload event
2024-04-13 11:40:28 +02:00
e01307a993 v4.20c 2024-04-13 11:39:26 +02:00
beb9f95359 Merge pull request #2051 from Phasip/patch-1
Clarify that oss-fuzz doesn't randomize builds anymore
2024-04-12 11:07:33 +02:00
c49a4c7027 Clarify that oss-fuzz doesn't randomize builds anymore 2024-04-12 09:28:38 +02:00
b08df87f5c fix syncing with custom mutator 2024-04-11 09:40:28 +02:00
72226d6f89 fix shared memory test cases 2024-04-09 16:20:42 +02:00
40adc34413 fix -V, code format 2024-04-09 09:24:19 +02:00
eeae114b76 Merge pull request #2034 from fbeqv/add_effective_fuzzing_time_tracker
Adds stats tracking for time spend actually mutating & running test i…
2024-04-09 09:04:53 +02:00
48a862c503 :Adds stats tracking time spend in calibration/trim/sync
This currently does not affect statsd nor the UI. Only the fuzzer_stats file is updated
2024-04-08 11:54:19 -07:00
29544e4d2b fix time 2024-04-07 18:44:21 +02:00
420a90ff75 code format 2024-04-07 12:53:41 +02:00
45603367bf fix llvm modules 2024-04-07 09:44:33 +02:00
f7ea0f569f fix aflpp custom mutator + standalone tool 2024-04-05 14:53:02 +02:00
2bf92848ff Fixed unicorn_dumper_gdb.py for updated version of gef (#2045)
Updated unicorn_dumper_gdb.py to support new gef api and replaced deprecated functions . The functions that are not in the new gef api are read_memory(), and current_arch(). Also replaced some deprecated functions with the updated versions of them.

    replaced read_memory() with GefMemoryManager.read() as read_memory(). read_memory() is in legacy-gef-api
    replaced current_arch with gef.arch.registers
    replaced get_process_maps() with gef.memory.maps (just depreacated)
    replaced get_register() with gef.arch.register()
2024-04-03 11:57:09 +02:00
ad65cfb400 Merge pull request #2043 from ligurio/ligurio/fix-clock_gettime
src: fix calculation of fuzzing time in statistics
2024-03-31 18:41:26 +07:00
5ffc8c7076 src: fix calculation of fuzzing time in statistics
When the computer is suspended during a fuzzing session,
the time spent in suspended state is counted as a "run time"
on a statistics screen.

The time returned by `gettimeofday(2)` is affected by discontinuous
jumps in the system time. It is better using `clock_gettime(2)`.

The patch replace `gettimeofday` with `clock_gettime` [1].
`clock_gettime` uses a CLOCK_MONOTONIC_COARSE clock type,
it is faster than CLOCK_MONOTONIC, but still has resolution (~1ms)
that is adequate for our purposes. However, CLOCK_MONOTONIC_COARSE
is a Linux-specific clock variant, so on macOS it is replaced
with CLOCK_MONOTONIC, and with CLOCK_MONOTONIC_FAST on FreeBSD [2].

Closes #1241

1. https://pubs.opengroup.org/onlinepubs/9699919799/functions/clock_gettime.html
2. https://man.freebsd.org/cgi/man.cgi?query=clock_gettime
2024-03-31 11:11:29 +03:00
8943ba0249 Merge pull request #2042 from ligurio/patch-1
citation: fix typo
2024-03-28 18:58:02 +07:00
b02adf6b3f citation: fix typo 2024-03-28 12:46:49 +03:00
6ef5d7c135 Merge pull request #2038 from SonicStark/dev-makefile-0322
bugfix: override directive and recipe echoing in GNUmakefile
2024-03-23 16:19:49 +07:00
9ece2e3f2c Merge pull request #2040 from flk0/stable
Fix build_qemu_support.sh static builds
2024-03-23 15:17:42 +07:00
4b2cdaf47c Fix build_qemu_support.sh static builds
The recently added config option 'enable-plugins' breaks static builds of qemuafl. Override the enable for static builds.
2024-03-23 15:39:54 +10:00
9b5b71b61b fix override directive and recipe echoing 2024-03-22 03:24:53 +00:00
59465bd249 Merge pull request #2035 from Resery/patch-6
bugfix: update_firda_version can't get the newest version of frida
2024-03-15 12:57:50 +07:00
ed50f37c79 bugfix: update_firda_version can't get the newest version of frida
The method of getting the newest version of Frida is invalid. Need update.
2024-03-15 12:03:01 +08:00
a96bda82f9 Merge pull request #2033 from gnbon/stable
Add -l option for adjustable block deletion performance in tmin
2024-03-15 08:39:39 +07:00
1860f6e594 Fix invalid range for del_len_limit 2024-03-14 11:00:59 +09:00
c9ad3acc9b Add -l option for adjustable block deletion
- Introduce the -l option to set min block deletion length using
powers of 2 (e.g., 1, 2, 4, 8, 16, ...).
- This enables a trade-off between minimization thoroughness and speed.
- Adjusting del_len_limit allows for faster processing, as doubling it
roughly halves the minimization time.
2024-03-13 12:10:38 +09:00
93c7a42453 Merge pull request #2029 from ocean1/minor_ver_fix
support parsing of llvm rc minor version
2024-03-12 15:30:27 +07:00
=
ee07fc9f6d fix rc minor version parsing 2024-03-12 08:20:08 +00:00
443edcd771 nits 2024-03-12 07:42:16 +01:00
6650ef4274 Merge pull request #2030 from ocean1/replay_loop_fix
Replay record loop fix
2024-03-12 10:08:29 +07:00
b85174fc8d nit 2024-03-12 04:00:19 +01:00
=
08f6d59f50 correct fix 2024-03-11 12:01:06 +00:00
=
2ed2ac80bc fix record compat loop to replay correct number of inputs, and at least one input 2024-03-11 10:30:35 +00:00
=
2300088446 support parsing of llvm rc minor version 2024-03-11 10:12:53 +00:00
306a917956 UI fix 2024-03-07 12:09:22 +01:00
0ea53ea5b5 likely 2024-03-06 12:41:00 +01:00
092260e9f9 Merge pull request #2026 from choller/pcmap_fix2
Fix delayed pcmap writing for code coverage with pc-table
2024-03-06 17:56:24 +07:00
52e19d35fa Add optional handling of Nyx InvalidWriteToPayload event 2024-03-06 10:55:53 +01:00
bf17953353 Code formating 2024-03-06 10:50:29 +01:00
e46fac6063 Fix delayed pcmap writing for code coverage with pc-table 2024-03-06 10:19:52 +01:00
6062668679 fix not using autodict 2024-02-29 14:31:47 +01:00
acc178e5dd log 2024-02-29 14:16:56 +01:00
31adb57fd7 Merge pull request #2014 from seanm/issue2007
Issue #2007: add filename extension to /crashes files
2024-02-29 14:16:07 +01:00
7652406c12 nit 2024-02-29 13:34:04 +01:00
a607adb7a3 Merge pull request #2019 from zidel/fork_server_fix
Load autodictionary when using new forkserver
2024-02-29 09:14:38 +01:00
036a79268b gcc cmplog fix 2024-02-29 09:10:29 +01:00
335b2d4542 Load autodictionary when using new forkserver
Fixes a bug where the new fork server would decrement dict_size until
zero then try to use it as the upper bound for the number of bytes to
pass to add_extra_func, causing it to never store any of the tokens.
2024-02-28 22:29:55 +01:00
603136efa0 unicornafl: Fix dump_regs() type errors in pwndbg dumper (#2005)
* push to stable (#1983)

* Output afl-clang-fast stuffs only if necessary (#1912)

* afl-cc header

* afl-cc common declarations

 - Add afl-cc-state.c
 - Strip includes, find_object, debug/be_quiet/have_*/callname setting from afl-cc.c
 - Use debugf_args in main
 - Modify execvp stuffs to fit new aflcc struct

* afl-cc show usage

* afl-cc mode selecting

1. compiler_mode by callname in argv[0]
2. compiler_mode by env "AFL_CC_COMPILER"
3. compiler_mode/instrument_mode by command line options "--afl-..."
4. instrument_mode/compiler_mode by various env vars including "AFL_LLVM_INSTRUMENT"
5. final checking steps
6. print "... - mode: %s-%s\n"
7. determine real argv[0] according to compiler_mode

* afl-cc macro defs

* afl-cc linking behaviors

* afl-cc fsanitize behaviors

* afl-cc misc

* afl-cc body update

* afl-cc all-in-one

formated with custom-format.py

* nits

---------

Co-authored-by: vanhauser-thc <vh@thc.org>

* changelog

* update grammar mutator

* lto llvm 12+

* docs(custom_mutators): fix missing ':' (#1953)

* Fix broken LTO mode and response file support (#1948)

* Strip `-Wl,-no-undefined` during compilation (#1952)

Make the compiler wrapper stripping `-Wl,-no-undefined` in addition to `-Wl,--no-undefined`.
Both versions of the flag are accepted by clang and, therefore, used by building systems in the wild (e.g., samba will not build without this fix).

* Remove dead code in write_to_testcase (#1955)

The custom_mutators_count check in if case is duplicate with if condition.
The else case is custom_mutators_count == 0, neither custom_mutator_list iteration nor sent check needed.

Signed-off-by: Xeonacid <h.dwwwwww@gmail.com>

* update qemuafl

* WIP: Add ability to generate drcov trace using QEMU backend (#1956)

* Document new drcov QEMU plugin

* Add link to lightkeeper for QEMU drcov file loading

---------

Co-authored-by: Jean-Romain Garnier <jean-romain.garnier@airbus.com>

* code format

* changelog

* sleep on uid != 0 afl-system-config

* fix segv about skip_next, warn on unsupported cases of linking options (#1958)

* todos

* ensure afl-cc only allows available compiler modes

* update grammar mutator

* disable aslr on apple

* fix for arm64

* help selective instrumentation

* typos

* macos

* add compiler test script

* apple fixes

* bump nyx submodules (#1963)

* fix docs

* update changelog

* update grammar mutator

* improve compiler test script

* gcc asan workaround (#1966)

* fix github merge fuckup

* fix

* Fix afl-cc (#1968)

- Check if too many cmdline params here, each time before insert a new param.
 - Check if it is "-fsanitize=..." before we do sth.
 - Remove improper param_st transfer.

* Avoid adding llvmnative instrumentation when linking rust sanitizer runtime (#1969)

* Dynamic instrumentation filtering for LLVM native (#1971)

* Add two dynamic instrumentation filter methods to runtime

* Always use pc-table with native pcguard

* Add make_symbol_list.py and README

* changelog

* todos

* new forkserver check

* fix

* nyx test for CI

* improve nyx docs

* Fixes to afl-cc and documentation (#1974)

* Always compile with -ldl when building for CODE_COVERAGE

When building with CODE_COVERAGE, the afl runtime contains code that
calls `dladdr` which requires -ldl. Under most circumstances, clang
already adds this (e.g. when building with pc-table), but there are some
circumstances where it isn't added automatically.

* Add visibility declaration to __afl_connected

When building with hidden visibility, the use of __AFL_LOOP inside such
code can cause linker errors due to __afl_connected being declared
"hidden".

* Update docs to clarify that CODE_COVERAGE=1 is required for dynamic_covfilter

* nits

* nyx build script updates

* test error output

* debug ci

* debug ci

* Improve afl-cc (#1975)

* update response file support

 - full support of rsp file
 - fix some segv issues

* Improve afl-cc

 - remove dead code about allow/denylist options of sancov
 - missing `if (!aflcc->have_msan)`
 - add docs for each function
 - typo

* enable nyx

* debug ci

* debug ci

* debug ci

* debug ci

* debug ci

* debug ci

* debug ci

* debug ci

* fix ci

* clean test script

* NO_NYX

* NO_NYX

* fix ci

* debug ci

* fix ci

* finalize ci fix

* Enhancement on Deterministic stage (#1972)

* fuzzer: init commit based on aflpp 60dc37a8cf

* fuzzers: adding the skip variables and initialize

* log: profile the det/havoc finding

* log: add profile log output

* fuzzers: sperate log/skipdet module

* fuzzers: add quick eff_map calc

* fuzzers: add skip_eff_map in fuzz_one

* fuzzers: mark whole input space in eff_map

* fuzzers: add undet bit threshold to skip some seeds

* fuzzers: fix one byte overflow

* fuzzers: fix overflow

* fix code format

* add havoc only again

* code format

* remove log to INTROSPECTION, rename skipdet module

* rename skipdet module

* remove log to stats

* clean redundant code

* code format

* remove redundant code format check

* remove redundant doc

* remove redundant objects

* clean files

* change -d to default skipdet

* disable deterministic when using CUSTOM_MUTATOR

* revert fix

* final touches for skipdet

* remove unused var

* remove redundant eff struct (#1977)

* update QEMU-Nyx submodule (#1978)

* update QEMU-Nyx submodule (#1980)

* Fix type in AFL_NOOPT env variable in afl-cc help message (#1982)

* nits

* 2024 v4.10c release

* fixes

---------

Signed-off-by: Xeonacid <h.dwwwwww@gmail.com>
Co-authored-by: Sonic <50692172+SonicStark@users.noreply.github.com>
Co-authored-by: Xeonacid <h.dwwwwww@gmail.com>
Co-authored-by: Nils Bars <nils.bars@rub.de>
Co-authored-by: Jean-Romain Garnier <7504819+JRomainG@users.noreply.github.com>
Co-authored-by: Jean-Romain Garnier <jean-romain.garnier@airbus.com>
Co-authored-by: Sergej Schumilo <sergej@schumilo.de>
Co-authored-by: Christian Holler (:decoder) <choller@mozilla.com>
Co-authored-by: Han Zheng <35988108+kdsjZh@users.noreply.github.com>
Co-authored-by: Khaled Yakdan <yakdan@code-intelligence.com>

* Fix dump_regs() type errors in Python

TypeError will occur as gdb api return some strange type of values that json can't serialize, this would fix this issue

* Update reg_val is None condition

---------

Signed-off-by: Xeonacid <h.dwwwwww@gmail.com>
Co-authored-by: van Hauser <vh@thc.org>
Co-authored-by: Sonic <50692172+SonicStark@users.noreply.github.com>
Co-authored-by: Xeonacid <h.dwwwwww@gmail.com>
Co-authored-by: Nils Bars <nils.bars@rub.de>
Co-authored-by: Jean-Romain Garnier <7504819+JRomainG@users.noreply.github.com>
Co-authored-by: Jean-Romain Garnier <jean-romain.garnier@airbus.com>
Co-authored-by: Sergej Schumilo <sergej@schumilo.de>
Co-authored-by: Christian Holler (:decoder) <choller@mozilla.com>
Co-authored-by: Han Zheng <35988108+kdsjZh@users.noreply.github.com>
Co-authored-by: Khaled Yakdan <yakdan@code-intelligence.com>
2024-02-27 09:46:07 +01:00
1e01ccc8fd unicornafl: Add UAF chcker to loader (#2009)
* impl uaf chcker

By adding a list of freed chunks, add the chunk to the list during free, check whether the allocated block is in the freed chunk list during malloc, and if so, remove the chunk from the freed chunk list, in __check_mem_access check whether the address is in the freed chunk list. This enables the detection of uaf.

* make uaf_check be configruable
2024-02-27 09:43:50 +01:00
9f6d27ddce Merge pull request #2018 from hyrathon/patch-2
Add -ldl flag
2024-02-27 08:57:23 +01:00
8fcd404352 Update GNUmakefile
The linker flags lacks a -ldl so the dlopen series of func symbols can't be found
2024-02-27 15:34:42 +08:00
b2b887d04d Issue #2007: add filename extension to /crashes files
This is very helpful for code that inpects a file name extension when determining what code to run.

It's also useful for applications that constrain the user to choose files by extension.
2024-02-26 14:07:49 -05:00
849994dedd update changelog 2024-02-23 14:09:22 +01:00
1286d1906f Merge pull request #2012 from clesmian/dev
Fix bug where `-t 1000+` may result in enormous timeouts
2024-02-23 13:53:15 +01:00
fae760fc9e Add upper and lower safety margins 2024-02-23 13:39:46 +01:00
01f442d810 Be specific about the unit of time 2024-02-23 12:53:20 +01:00
eaedf2e62f Adhere to documented behavior 2024-02-23 12:52:11 +01:00
07e0b39126 Do not circumvent sanity checks from arg parsing 2024-02-22 15:55:18 +01:00
98238ed763 Convert from microseconds (us) to milliseconds (ms) 2024-02-22 15:28:55 +01:00
340d6aa97c unicornafl: fix malloc of size 0 (#2010)
* bugfix: free a chunk with a size of 0, it will cause 1 byte oob.

Malloc does not check the size. Generally, malloc(0) should return 0 but there will return two pages. Free will use is_buffer_in_chunk to check whether the address is in the chunk. At that time, the chunk.data_addr == total_size . Free pass address and "1" to is_buffer_in_chunk. So cause 1 byte out-of-bound.

* typo
2024-02-21 12:42:55 +01:00
5ae4a7ae02 afl-whatsup current speed 2024-02-20 15:48:48 +01:00
80158de3e8 Catch invalid frees (#2008)
1. There isn't a need to check all chunks when address == 0
2. If the address is not in chunks, the program may want to free an object that doesn't exist. There may be a "double-free" or "invalid-free" vulnerability. (This patch is from the repo named "Battelle/afl-unicorn")
2024-02-20 14:01:37 +01:00
730713193a replaced unicornafl with unicorn (#2003)
* push to stable (#1983)

* Output afl-clang-fast stuffs only if necessary (#1912)

* afl-cc header

* afl-cc common declarations

 - Add afl-cc-state.c
 - Strip includes, find_object, debug/be_quiet/have_*/callname setting from afl-cc.c
 - Use debugf_args in main
 - Modify execvp stuffs to fit new aflcc struct

* afl-cc show usage

* afl-cc mode selecting

1. compiler_mode by callname in argv[0]
2. compiler_mode by env "AFL_CC_COMPILER"
3. compiler_mode/instrument_mode by command line options "--afl-..."
4. instrument_mode/compiler_mode by various env vars including "AFL_LLVM_INSTRUMENT"
5. final checking steps
6. print "... - mode: %s-%s\n"
7. determine real argv[0] according to compiler_mode

* afl-cc macro defs

* afl-cc linking behaviors

* afl-cc fsanitize behaviors

* afl-cc misc

* afl-cc body update

* afl-cc all-in-one

formated with custom-format.py

* nits

---------

Co-authored-by: vanhauser-thc <vh@thc.org>

* changelog

* update grammar mutator

* lto llvm 12+

* docs(custom_mutators): fix missing ':' (#1953)

* Fix broken LTO mode and response file support (#1948)

* Strip `-Wl,-no-undefined` during compilation (#1952)

Make the compiler wrapper stripping `-Wl,-no-undefined` in addition to `-Wl,--no-undefined`.
Both versions of the flag are accepted by clang and, therefore, used by building systems in the wild (e.g., samba will not build without this fix).

* Remove dead code in write_to_testcase (#1955)

The custom_mutators_count check in if case is duplicate with if condition.
The else case is custom_mutators_count == 0, neither custom_mutator_list iteration nor sent check needed.

Signed-off-by: Xeonacid <h.dwwwwww@gmail.com>

* update qemuafl

* WIP: Add ability to generate drcov trace using QEMU backend (#1956)

* Document new drcov QEMU plugin

* Add link to lightkeeper for QEMU drcov file loading

---------

Co-authored-by: Jean-Romain Garnier <jean-romain.garnier@airbus.com>

* code format

* changelog

* sleep on uid != 0 afl-system-config

* fix segv about skip_next, warn on unsupported cases of linking options (#1958)

* todos

* ensure afl-cc only allows available compiler modes

* update grammar mutator

* disable aslr on apple

* fix for arm64

* help selective instrumentation

* typos

* macos

* add compiler test script

* apple fixes

* bump nyx submodules (#1963)

* fix docs

* update changelog

* update grammar mutator

* improve compiler test script

* gcc asan workaround (#1966)

* fix github merge fuckup

* fix

* Fix afl-cc (#1968)

- Check if too many cmdline params here, each time before insert a new param.
 - Check if it is "-fsanitize=..." before we do sth.
 - Remove improper param_st transfer.

* Avoid adding llvmnative instrumentation when linking rust sanitizer runtime (#1969)

* Dynamic instrumentation filtering for LLVM native (#1971)

* Add two dynamic instrumentation filter methods to runtime

* Always use pc-table with native pcguard

* Add make_symbol_list.py and README

* changelog

* todos

* new forkserver check

* fix

* nyx test for CI

* improve nyx docs

* Fixes to afl-cc and documentation (#1974)

* Always compile with -ldl when building for CODE_COVERAGE

When building with CODE_COVERAGE, the afl runtime contains code that
calls `dladdr` which requires -ldl. Under most circumstances, clang
already adds this (e.g. when building with pc-table), but there are some
circumstances where it isn't added automatically.

* Add visibility declaration to __afl_connected

When building with hidden visibility, the use of __AFL_LOOP inside such
code can cause linker errors due to __afl_connected being declared
"hidden".

* Update docs to clarify that CODE_COVERAGE=1 is required for dynamic_covfilter

* nits

* nyx build script updates

* test error output

* debug ci

* debug ci

* Improve afl-cc (#1975)

* update response file support

 - full support of rsp file
 - fix some segv issues

* Improve afl-cc

 - remove dead code about allow/denylist options of sancov
 - missing `if (!aflcc->have_msan)`
 - add docs for each function
 - typo

* enable nyx

* debug ci

* debug ci

* debug ci

* debug ci

* debug ci

* debug ci

* debug ci

* debug ci

* fix ci

* clean test script

* NO_NYX

* NO_NYX

* fix ci

* debug ci

* fix ci

* finalize ci fix

* Enhancement on Deterministic stage (#1972)

* fuzzer: init commit based on aflpp 60dc37a8cf

* fuzzers: adding the skip variables and initialize

* log: profile the det/havoc finding

* log: add profile log output

* fuzzers: sperate log/skipdet module

* fuzzers: add quick eff_map calc

* fuzzers: add skip_eff_map in fuzz_one

* fuzzers: mark whole input space in eff_map

* fuzzers: add undet bit threshold to skip some seeds

* fuzzers: fix one byte overflow

* fuzzers: fix overflow

* fix code format

* add havoc only again

* code format

* remove log to INTROSPECTION, rename skipdet module

* rename skipdet module

* remove log to stats

* clean redundant code

* code format

* remove redundant code format check

* remove redundant doc

* remove redundant objects

* clean files

* change -d to default skipdet

* disable deterministic when using CUSTOM_MUTATOR

* revert fix

* final touches for skipdet

* remove unused var

* remove redundant eff struct (#1977)

* update QEMU-Nyx submodule (#1978)

* update QEMU-Nyx submodule (#1980)

* Fix type in AFL_NOOPT env variable in afl-cc help message (#1982)

* nits

* 2024 v4.10c release

* fixes

---------

Signed-off-by: Xeonacid <h.dwwwwww@gmail.com>
Co-authored-by: Sonic <50692172+SonicStark@users.noreply.github.com>
Co-authored-by: Xeonacid <h.dwwwwww@gmail.com>
Co-authored-by: Nils Bars <nils.bars@rub.de>
Co-authored-by: Jean-Romain Garnier <7504819+JRomainG@users.noreply.github.com>
Co-authored-by: Jean-Romain Garnier <jean-romain.garnier@airbus.com>
Co-authored-by: Sergej Schumilo <sergej@schumilo.de>
Co-authored-by: Christian Holler (:decoder) <choller@mozilla.com>
Co-authored-by: Han Zheng <35988108+kdsjZh@users.noreply.github.com>
Co-authored-by: Khaled Yakdan <yakdan@code-intelligence.com>

* replaced unicornafl with unicorn

The submodule of unicorn cannot be imported through unicornafl.*_const here. If we want to use the *_const module, we should reference `from unicorn.*_const import *` like this instead of importing the entire contents of the *_const module via unicornafl。

---------

Signed-off-by: Xeonacid <h.dwwwwww@gmail.com>
Co-authored-by: van Hauser <vh@thc.org>
Co-authored-by: Sonic <50692172+SonicStark@users.noreply.github.com>
Co-authored-by: Xeonacid <h.dwwwwww@gmail.com>
Co-authored-by: Nils Bars <nils.bars@rub.de>
Co-authored-by: Jean-Romain Garnier <7504819+JRomainG@users.noreply.github.com>
Co-authored-by: Jean-Romain Garnier <jean-romain.garnier@airbus.com>
Co-authored-by: Sergej Schumilo <sergej@schumilo.de>
Co-authored-by: Christian Holler (:decoder) <choller@mozilla.com>
Co-authored-by: Han Zheng <35988108+kdsjZh@users.noreply.github.com>
Co-authored-by: Khaled Yakdan <yakdan@code-intelligence.com>
2024-02-19 22:44:05 +01:00
fea76dff23 Merge pull request #1999 from seanm/issue1865
Fixed #1865: create symlinks for afl-clang-fast
2024-02-19 19:07:30 +01:00
808022d3e0 Fixed #1865: many updates to INSTALL.md for macOS
- moved shared mem instructions to before building so that tests during build don't fail
- corrected path to README.llvm.md
- updated some macOS spelling
- added missing sudo
- misc other changes from reading the document carefully
2024-02-19 12:06:11 -05:00
eee78077e2 Merge pull request #1998 from trail-of-forks/grub-cmdline
afl-persistent-config: Use GRUB_CMDLINE_LINUX instead of GRUB_CMDLINE_LINUX_DEFAULT
2024-02-16 18:22:30 +01:00
ca91d3fbc0 Revert other changes 2024-02-16 13:54:05 +00:00
ad4a776fc6 Change both 2024-02-16 12:01:50 +00:00
ebdb71aeb0 Merge pull request #2002 from seanm/issue2001
issue #2001: fix passing rpath to linker on macOS
2024-02-16 10:14:56 +01:00
6dc58750cf issue #2001: fix passing rpath to linker on macOS
Seems on macOS, `ld` does not want an `=` when specifying `-rpath`.
2024-02-15 19:19:51 -05:00
1b84448be3 afl-persistent-config: Use GRUB_CMDLINE_LINUX instead of GRUB_CMDLINE_LINUX_DEFAULT.
The latter is often overwritten in images used in cloud setups. For example DigitalOcean sets GRUB_CMDLINE_LINUX_DEFAULT="console=tty1 console=ttyS0" in /etc/default/grub.d/
2024-02-14 15:55:32 +00:00
61ceef64b1 valid comparison.md 2024-02-13 20:14:35 +01:00
5404eef7be update docs 2024-02-09 17:08:23 +01:00
6fed799957 unicorn fix 2024-02-09 14:14:12 +01:00
dd88069711 fix 2024-02-09 13:57:45 +01:00
07bc202e0a fixes 2024-02-09 13:51:05 +01:00
f2b7357ff3 fixes 2024-02-09 13:09:23 +01:00
3cbaefd247 Merge pull request #1995 from seanm/issue1981
Fixed issue #1981: document PATH correctly based on homebrew version
2024-02-09 10:31:38 +01:00
037a14f621 Fixed issue #1981: document PATH correctly based on homebrew version
- removed reference to M1 as M2 and M3 exist now too.
- Also use current name and spelling of "macOS".
2024-02-08 21:15:59 -05:00
88e41f01c8 env fix 2024-02-08 15:28:19 +01:00
369fce9c85 code format 2024-02-08 15:13:46 +01:00
eaf4a29930 make redqueen hashmap not default 2024-02-08 14:54:10 +01:00
48070e0148 Merge branch '420' into dev 2024-02-08 14:51:13 +01:00
c23bbddde9 workaround for MOpt bug with -S 2024-02-08 14:31:36 +01:00
038fef962c performance 2024-02-08 12:46:08 +01:00
42c663e7c7 Merge pull request #1965 from CodeLinaro/stateful
replay mode support
2024-02-08 10:29:33 +01:00
956fa95d77 updated readme 2024-02-07 12:00:11 +01:00
ea0ea88ed3 add conditional check for persistent record mode on forkserver handling of hang/crash 2024-02-07 12:00:01 +01:00
e0e8645d6c Merge pull request #1990 from monik3r/dev
Add 7950x3d and 6900hs benchmarks, with and without mitigations
2024-02-07 09:03:01 +01:00
a2100f32e0 Add missing jsonl entry. Thanks @cjb! 2024-02-06 21:00:43 -08:00
25a6c2c006 Add benmark-results.jsonl 2024-02-06 20:39:34 -08:00
7f8347b12e Add 7950x3d and 6900hs benchmarks, with and without mitigations 2024-02-06 20:24:31 -08:00
8e4bd0314e added README.md to utils/replay_record 2024-02-06 21:34:56 +01:00
a7fd84e186 fix typo 2024-02-06 21:25:40 +01:00
e405e721fa reuse first_pass aux var in persistent loop for record replay mode, keep area ptr and loc logic intact in record replay mode, move replay record example to own dir in utils, update docs, move record compat layer to separate header file 2024-02-06 18:19:52 +01:00
49d4fa4346 add replay_record binaries to .gitignore 2024-02-06 18:16:37 +01:00
375aca2997 nits 2024-02-06 14:49:21 +01:00
9f8eea5467 add spec_rstack_overflow=off to persistent-config 2024-02-06 14:25:39 +01:00
58aa181d01 revert persistent_demo_new.c to b99bbf671b 2024-02-06 14:00:37 +01:00
f49e391022 prevent afl-whatsup tmp files 2024-02-06 10:48:24 +01:00
698f1e272b fix hashmap test 2024-02-06 09:34:21 +01:00
023fc19ce0 better replay mode error handling, added replay mode documentation, code formatting 2024-02-05 18:26:46 +01:00
40df85d1e6 adjust cmplog header 2024-02-05 15:05:46 +01:00
47e7d243f7 increase version 2024-02-04 16:18:21 +01:00
6d209ce045 fix -z 2024-02-04 16:16:32 +01:00
34a3060b0f config __afl_cmplog_max_len 2024-02-04 16:08:57 +01:00
c77709cdd9 add U256/32byte support 2024-02-04 16:03:12 +01:00
27338fcef1 new forkserver - client side 2024-02-03 18:27:01 +01:00
9fab7e892d new forkserver - server part 2024-02-03 16:48:38 +01:00
dc151caa18 add lto caller instrumentation 2024-02-03 15:53:54 +01:00
e1d7f4af35 Merge pull request #1988 from AFLplusplus/ltoctx
Ltoctx
2024-02-03 15:08:52 +01:00
d85722a4f6 deterministic fuzzing and -z 2024-02-03 13:31:31 +01:00
ba3a039e45 finish lto-ctx 2024-02-02 13:17:20 +01:00
bd13d32437 final touches 2024-02-02 09:54:24 +01:00
79080355ac better CTX instrumentation 2024-02-01 17:39:23 +01:00
e6eee685ce fix 2024-01-27 15:13:27 +01:00
ceb7e44e6f fixes 2024-01-27 08:28:47 +01:00
d668010bed fixes 2024-01-26 16:44:31 +01:00
44a7696169 fixes 2024-01-26 15:27:20 +01:00
b0a912a838 working ugly version 2024-01-26 12:15:42 +01:00
4d493452a4 tmp 2024-01-25 17:00:53 +01:00
8fedf49984 replay mode support 2024-01-23 19:36:49 +01:00
114 changed files with 9351 additions and 2790 deletions

5
.gitignore vendored
View File

@ -99,10 +99,15 @@ unicorn_mode/samples/*/\.test-*
utils/afl_network_proxy/afl-network-client
utils/afl_network_proxy/afl-network-server
utils/afl_proxy/afl-proxy
utils/bench/hash
utils/optimin/build
utils/optimin/optimin
utils/persistent_mode/persistent_demo
utils/persistent_mode/persistent_demo_new
utils/persistent_mode/persistent_demo_new_compat
utils/persistent_mode/test-instr
utils/replay_record/persistent_demo_replay
utils/replay_record/persistent_demo_replay_compat
utils/replay_record/persistent_demo_replay_argparse
utils/plot_ui/afl-plot-ui
vuln_prog

4
.gitmodules vendored
View File

@ -25,3 +25,7 @@
[submodule "nyx_mode/QEMU-Nyx"]
path = nyx_mode/QEMU-Nyx
url = https://github.com/nyx-fuzz/QEMU-Nyx
[submodule "xgboost"]
path = xgboost
url = https://github.com/dmlc/xgboost
branch = 742c19f

View File

@ -27,5 +27,5 @@ keywords:
- qemu
- llvm
- unicorn-emulator
- securiy
- security
license: AGPL-3.0-or-later

View File

@ -52,7 +52,7 @@ endif
ifdef ASAN_BUILD
$(info Compiling ASAN version of binaries)
override CFLAGS += $(ASAN_CFLAGS)
LDFLAGS += $(ASAN_LDFLAGS)
override LDFLAGS += $(ASAN_LDFLAGS)
endif
ifdef UBSAN_BUILD
$(info Compiling UBSAN version of binaries)
@ -84,38 +84,44 @@ else
endif
endif
#ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -fno-move-loop-invariants -fdisable-tree-cunrolli -x c - -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
# SPECIAL_PERFORMANCE += -fno-move-loop-invariants -fdisable-tree-cunrolli
#endif
#ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
# ifndef SOURCE_DATE_EPOCH
# HAVE_MARCHNATIVE = 1
# CFLAGS_OPT += -march=native
# endif
#endif
ifdef PERFORMANCE
SPECIAL_PERFORMANCE := -D_AFL_SPECIAL_PERFORMANCE
ifeq "$(SYS)" "Linux"
ifeq "$(shell grep avx2 /proc/cpuinfo)" ""
else
SPECIAL_PERFORMANCE += -mavx2 -D_HAVE_AVX2
endif
endif
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
HAVE_MARCHNATIVE = 1
SPECIAL_PERFORMANCE += -march=native
endif
$(info SPECIAL_PERFORMANCE=$(SPECIAL_PERFORMANCE))
else
SPECIAL_PERFORMANCE :=
endif
ifneq "$(SYS)" "Darwin"
#ifeq "$(HAVE_MARCHNATIVE)" "1"
# SPECIAL_PERFORMANCE += -march=native
#endif
#ifndef DEBUG
# CFLAGS_OPT += -D_FORTIFY_SOURCE=1
# override CFLAGS_OPT += -D_FORTIFY_SOURCE=1
#endif
else
# On some odd MacOS system configurations, the Xcode sdk path is not set correctly
SDK_LD = -L$(shell xcrun --show-sdk-path)/usr/lib
LDFLAGS += $(SDK_LD)
override LDFLAGS += $(SDK_LD)
endif
COMPILER_TYPE=$(shell $(CC) --version|grep "Free Software Foundation")
ifneq "$(COMPILER_TYPE)" ""
#$(info gcc is being used)
CFLAGS_OPT += -Wno-error=format-truncation -Wno-format-truncation
override CFLAGS_OPT += -Wno-error=format-truncation -Wno-format-truncation
endif
ifeq "$(SYS)" "SunOS"
LDFLAGS = -lkstat -lrt -lsocket -lnsl
override LDFLAGS = -lkstat -lrt -lsocket -lnsl
endif
ifdef STATIC
@ -125,8 +131,8 @@ ifdef STATIC
PYFLAGS=
PYTHON_INCLUDE = /
CFLAGS_OPT += -static
LDFLAGS += -lm -lpthread -lz -lutil
override CFLAGS_OPT += -static
override LDFLAGS += -lm -lpthread -lz -lutil
endif
ifdef PROFILING
@ -389,6 +395,7 @@ help:
@echo
@echo Known build environment options:
@echo "=========================================="
@echo "PERFORMANCE - compile with performance options that make the binary not transferable to other systems. Recommended!"
@echo STATIC - compile AFL++ static
@echo "CODE_COVERAGE - compile the target for code coverage (see docs/instrumentation/README.llvm.md)"
@echo ASAN_BUILD - compiles AFL++ with memory sanitizer for debug purposes
@ -453,31 +460,36 @@ afl-as: src/afl-as.c include/afl-as.h $(COMM_HDR) | test_x86
@ln -sf afl-as as
src/afl-performance.o : $(COMM_HDR) src/afl-performance.c include/hash.h
$(CC) $(CFLAGS) $(CFLAGS_OPT) -Iinclude -c src/afl-performance.c -o src/afl-performance.o
$(CC) $(CFLAGS) $(CFLAGS_OPT) $(SPECIAL_PERFORMANCE) -Iinclude -c src/afl-performance.c -o src/afl-performance.o
src/afl-common.o : $(COMM_HDR) src/afl-common.c include/common.h
$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-common.c -o src/afl-common.o
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-common.c -o src/afl-common.o
src/afl-forkserver.o : $(COMM_HDR) src/afl-forkserver.c include/forkserver.h
$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-forkserver.c -o src/afl-forkserver.o
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-forkserver.c -o src/afl-forkserver.o
src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h
$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS) -lm
libxgboost.so:
git submodule init
git submodule update --recursive
mkdir -p xgboost/build && cd xgboost && git submodule init && git submodule update --recursive && cd build && cmake -DUSE_OPENMP=OFF -DHIDE_CXX_SYMBOLS=ON .. && make && cp -v ../lib/libxgboost.so ../..
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o src/hashmap.c libxgboost.so | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -Wno-shift-count-overflow $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o src/hashmap.c -o $@ $(PYFLAGS) $(LDFLAGS) -I./xgboost/include -lm -L. -lxgboost
afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-fuzz-mutators.c src/afl-fuzz-python.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS)
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-fuzz-mutators.c src/afl-fuzz-python.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS)
afl-tmin: src/afl-tmin.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(LDFLAGS)
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(LDFLAGS)
afl-analyze: src/afl-analyze.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o src/afl-forkserver.o $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o src/afl-forkserver.o -o $@ $(LDFLAGS)
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o src/afl-forkserver.o -o $@ $(LDFLAGS)
afl-gotcpu: src/afl-gotcpu.c src/afl-common.o $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o -o $@ $(LDFLAGS)
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-common.o -o $@ $(LDFLAGS)
.PHONY: document
document: afl-fuzz-document
@ -494,17 +506,17 @@ unit_maybe_alloc: test/unittests/unit_maybe_alloc.o
./test/unittests/unit_maybe_alloc
test/unittests/unit_hash.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_hash.c $(AFL_FUZZ_FILES) src/afl-performance.o
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_hash.c -o test/unittests/unit_hash.o
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -c test/unittests/unit_hash.c -o test/unittests/unit_hash.o
unit_hash: test/unittests/unit_hash.o src/afl-performance.o
@$(CC) $(CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_hash $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
@$(CC) $(CFLAGS) $(SPECIAL_PERFORMANCE) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_hash $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
./test/unittests/unit_hash
test/unittests/unit_rand.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_rand.c $(AFL_FUZZ_FILES) src/afl-performance.o
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_rand.c -o test/unittests/unit_rand.o
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -c test/unittests/unit_rand.c -o test/unittests/unit_rand.o
unit_rand: test/unittests/unit_rand.o src/afl-common.o src/afl-performance.o
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_rand $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_rand $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
./test/unittests/unit_rand
test/unittests/unit_list.o : $(COMM_HDR) include/list.h test/unittests/unit_list.c $(AFL_FUZZ_FILES)
@ -752,7 +764,7 @@ endif
@test -e SanitizerCoveragePCGUARD.so && echo "[+] LLVM mode successfully built" || echo "[-] LLVM mode could not be built, please install at least llvm-13 and clang-13 or newer, see docs/INSTALL.md"
@test -e SanitizerCoverageLTO.so && echo "[+] LLVM LTO mode successfully built" || echo "[-] LLVM LTO mode could not be built, it is optional, if you want it, please install LLVM 11-14. More information at instrumentation/README.lto.md on how to build it"
ifneq "$(SYS)" "Darwin"
test -e afl-gcc-pass.so && echo "[+] gcc_mode successfully built" || echo "[-] gcc_mode could not be built, it is optional, install gcc-VERSION-plugin-dev to enable this"
@test -e afl-gcc-pass.so && echo "[+] gcc_mode successfully built" || echo "[-] gcc_mode could not be built, it is optional, install gcc-VERSION-plugin-dev to enable this"
endif
ifeq "$(SYS)" "Linux"
ifndef NO_NYX

View File

@ -44,9 +44,9 @@ endif
LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/git//' | sed 's/svn//' )
LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//' )
LLVM_MINOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/.*\.//' | sed 's/git//' | sed 's/svn//' | sed 's/ .*//' )
LLVM_MINOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/.*\.//' | sed 's/git//' | sed 's/svn//' | sed 's/ .*//' | sed 's/rc.*//' )
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[0-2]\.|^3.[0-8]\.' && echo 1 || echo 0 )
LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[8-9]|^2[0-9]' && echo 1 || echo 0 )
LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^19|^2[0-9]' && echo 1 || echo 0 )
LLVM_TOO_OLD = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[1-9]\.|^1[012]\.' && echo 1 || echo 0 )
LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[0-9]' && echo 1 || echo 0 )
LLVM_NEWER_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[6-9]' && echo 1 || echo 0 )

View File

@ -2,9 +2,9 @@
<img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/main/static/aflpp_bg.svg" alt="AFL++ logo" width="250" heigh="250">
Release version: [4.10c](https://github.com/AFLplusplus/AFLplusplus/releases)
Release version: [4.20c](https://github.com/AFLplusplus/AFLplusplus/releases)
GitHub version: 4.10c
GitHub version: 4.21a
Repository:
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)

View File

@ -2,22 +2,22 @@
## Must
- UI revamp
- hardened_usercopy=0 page_alloc.shuffle=0
- add value_profile but only enable after 15 minutes without finds
- cmplog max len, cmplog max items envs?
- cmplog max items env?
- adapt MOpt to new mutation engine
- Update afl->pending_not_fuzzed for MOpt
- cmplog rtn sanity check on fixed length? currently we ignore the length
- afl-showmap -f support
- afl-fuzz multicore wrapper script
- when trimming then perform crash detection
- problem: either -L0 and/or -p mmopt results in zero new coverage
- cyclomatic complexity: 2 + calls + edges - blocks
## Should
- afl-crash-analysis
- cmplog: add loop count resolving (byte -> loop cnt change, calc special values)
- support persistent and deferred fork server in afl-showmap?
- better autodetection of shifting runtime timeout values
- afl-plot to support multiple plot_data

View File

@ -13,7 +13,7 @@ awk -f - -- ${@+"$@"} <<'EOF'
# awk script to minimize a test corpus of input files
#
# based on afl-cmin bash script written by Michal Zalewski
# rewritten by Heiko Eißfeldt (hexcoder-)
# rewritten by Heiko Eissfeldt (hexcoder-)
# tested with:
# gnu awk (x86 Linux)
# bsd awk (x86 *BSD)
@ -108,7 +108,7 @@ function usage() {
"\n" \
"Execution control settings:\n" \
" -T tasks - how many parallel tasks to run (default: 1, all=nproc)\n" \
" -f file - location read by the fuzzed program (stdin)\n" \
" -f file - location read by the fuzzed program (default: stdin)\n" \
" -m megs - memory limit for child process ("mem_limit" MB)\n" \
" -t msec - run time limit for child process (default: 5000)\n" \
" -O - use binary-only instrumentation (FRIDA mode)\n" \
@ -603,8 +603,8 @@ BEGIN {
# create path for the trace file from afl-showmap
tracefile_path = trace_dir"/"fn
# ensure the file size is not zero
cmd = "du -b "tracefile_path
"ls -l "tracefile_path
cmd = "du -b \""tracefile_path"\""
# "ls -l \""tracefile_path"\""
cmd | getline output
close(cmd)
split(output, result, "\t")

View File

@ -152,6 +152,7 @@ Minimization settings:
-e - solve for edge coverage only, ignore hit counts
For additional tips, please consult README.md.
This script cannot read filenames that end with a space ' '.
Environment variables used:
AFL_KEEP_TRACES: leave the temporary <out_dir>\.traces directory

View File

@ -124,17 +124,26 @@ kernel.sched_latency_ns=250000000
EOF
}
grep -E -q '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub 2>/dev/null || echo Error: /etc/default/grub with GRUB_CMDLINE_LINUX_DEFAULT is not present, cannot set boot options
grep -E -q '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub 2>/dev/null && {
grep -E '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub | grep -E -q 'noibrs pcid nopti' || {
grub_try_disable_mitigation () {
KEY="$1"
if ! grep -E "^$KEY=" /etc/default/grub | grep -E -q 'noibrs pcid nopti'; then
echo "Configuring performance boot options"
LINE=`grep -E '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub | sed 's/^GRUB_CMDLINE_LINUX_DEFAULT=//' | tr -d '"'`
OPTIONS="$LINE ibpb=off ibrs=off kpti=off l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs pcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=on pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx=on tsx_async_abort=off mitigations=off audit=0 hardened_usercopy=off ssbd=force-off"
echo Setting boot options in /etc/default/grub to GRUB_CMDLINE_LINUX_DEFAULT=\"$OPTIONS\"
sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=.*|GRUB_CMDLINE_LINUX_DEFAULT=\"$OPTIONS\"|" /etc/default/grub
}
LINE=`grep -E "^$KEY=" /etc/default/grub | sed "s/^$KEY=//" | tr -d '"'`
OPTIONS="$LINE ibpb=off ibrs=off kpti=off l1tf=off spec_rstack_overflow=off mds=off no_stf_barrier noibpb noibrs pcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=on pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx=on tsx_async_abort=off mitigations=off audit=0 hardened_usercopy=off ssbd=force-off"
echo Setting boot options in /etc/default/grub to $KEY=\"$OPTIONS\"
sed -i "s|^$KEY=.*|$KEY=\"$OPTIONS\"|" /etc/default/grub
fi
}
if grep -E -q '^GRUB_CMDLINE_LINUX=' /etc/default/grub || grep -E -q '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub; then
grub_try_disable_mitigation "GRUB_CMDLINE_LINUX_DEFAULT"
# We also overwrite GRUB_CMDLINE_LINUX because some distributions already overwrite GRUB_CMDLINE_LINUX_DEFAULT
grub_try_disable_mitigation "GRUB_CMDLINE_LINUX"
else
echo "Error: /etc/default/grub with GRUB_CMDLINE_LINUX is not present, cannot set boot options"
fi
echo
echo "Reboot and enjoy your fuzzing"
exit 0

View File

@ -111,9 +111,16 @@ if [ -z "$NO_COLOR" ]; then
RESET="$NC"
fi
PLATFORM=`uname -s`
if [ "$PLATFORM" = "Linux" ] ; then
CUR_TIME=`cat /proc/uptime | awk '{printf "%.0f\n", $1}'`
else
# This will lead to inacurate results but will prevent the script from breaking on platforms other than Linux
CUR_TIME=`date +%s`
fi
TMP=`mktemp -t .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || exit 1
trap "rm -f $TMP" 1 2 3 13 15
ALIVE_CNT=0
DEAD_CNT=0
@ -122,6 +129,7 @@ START_CNT=0
TOTAL_TIME=0
TOTAL_EXECS=0
TOTAL_EPS=0
TOTAL_EPLM=0
TOTAL_CRASHES=0
TOTAL_HANGS=0
TOTAL_PFAV=0
@ -181,6 +189,8 @@ for j in `find . -maxdepth 2 -iname fuzzer_setup | sort`; do
if [ -f "$i" ]; then
IS_STARTING=
IS_DEAD=
sed 's/^command_line.*$/_skip:1/;s/[ ]*:[ ]*/="/;s/$/"/' "$i" >"$TMP"
. "$TMP"
DIRECTORY=$DIR
@ -211,9 +221,6 @@ for j in `find . -maxdepth 2 -iname fuzzer_setup | sort`; do
if ! kill -0 "$fuzzer_pid" 2>/dev/null; then
IS_STARTING=
IS_DEAD=
if [ -e "$i" ] && [ -e "$j" ] && [ -n "$FUSER" ]; then
if [ "$i" -ot "$j" ]; then
@ -272,11 +279,15 @@ for j in `find . -maxdepth 2 -iname fuzzer_setup | sort`; do
ALIVE_CNT=$((ALIVE_CNT + 1))
EXEC_SEC=0
EXEC_MIN=0
test -z "$RUN_UNIX" -o "$RUN_UNIX" = 0 || EXEC_SEC=$((execs_done / RUN_UNIX))
PATH_PERC=$((cur_item * 100 / corpus_count))
test "$IS_DEAD" = 1 || EXEC_MIN=$(echo $execs_ps_last_min|sed 's/\..*//')
TOTAL_TIME=$((TOTAL_TIME + RUN_UNIX))
TOTAL_EPS=$((TOTAL_EPS + EXEC_SEC))
TOTAL_EPLM=$((TOTAL_EPLM + EXEC_MIN))
TOTAL_EXECS=$((TOTAL_EXECS + execs_done))
TOTAL_CRASHES=$((TOTAL_CRASHES + saved_crashes))
TOTAL_HANGS=$((TOTAL_HANGS + saved_hangs))
@ -412,9 +423,12 @@ echo " Total run time : $FMT_TIME"
if [ -z "$MINIMAL_ONLY" ]; then
echo " Total execs : $FMT_EXECS"
echo " Cumulative speed : $TOTAL_EPS execs/sec"
if [ "$ALIVE_CNT" -gt "0" ]; then
echo " Total average speed : $((TOTAL_EPS / ALIVE_CNT)) execs/sec"
fi
fi
if [ "$ALIVE_CNT" -gt "0" ]; then
echo " Average speed : $((TOTAL_EPS / ALIVE_CNT)) execs/sec"
echo "Current average speed : $TOTAL_EPLM execs/sec"
fi
if [ -z "$MINIMAL_ONLY" ]; then
echo " Pending items : $TOTAL_PFAV faves, $TOTAL_PENDING total"

View File

@ -1,9 +1,13 @@
CPU | MHz | threads | singlecore | multicore | afl-*-config |
====================================================|=======|=========|============|===========|==============|
Raspberry Pi 5 | 2400 | 4 | 25786 | 101114 | both |
AMD EPYC 7282 16-Core Processor | 3194 | 32 | 87199 | 769001 | both |
AMD Ryzen 5 PRO 4650G with Radeon Graphics | 3700 | 12 | 95356 | 704840 | both |
Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz | 4995 | 16 | 120064 | 1168943 | both |
12th Gen Intel(R) Core(TM) i7-1270P | 4761 | 16 | 149778 | 641219 | both |
AMD Ryzen 9 5950X 16-Core Processor | 4792 | 32 | 161690 | 2339763 | both |
Apple Mac Studio M2 Ultra 2023, Linux VM guest | 3500 | 16 | 163570 | 1157465 | both |
|CPU | MHz | threads | singlecore | multicore | afl-*-config |
|----------------------------------------------------|-------|---------|------------|-----------|--------------|
|Raspberry Pi 5 | 2400 | 4 | 25786 | 101114 | both |
|AMD EPYC 7282 16-Core Processor | 3194 | 32 | 87199 | 769001 | both |
|AMD Ryzen 5 PRO 4650G with Radeon Graphics | 3700 | 12 | 95356 | 704840 | both |
|Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz | 4995 | 16 | 120064 | 1168943 | both |
|12th Gen Intel(R) Core(TM) i7-1270P | 4761 | 16 | 149778 | 641219 | both |
|AMD Ryzen 9 5950X 16-Core Processor | 4792 | 32 | 161690 | 2339763 | both |
|Apple Mac Studio M2 Ultra 2023, Linux VM guest | 3500 | 16 | 163570 | 1157465 | both |
|AMD Ryzen 9 6900HS with Radeon Graphics | 4676 | 16 | 62860 | 614404 | system |
|AMD Ryzen 9 6900HS with Radeon Graphics | 4745 | 16 | 135501 | 991133 | both |
|AMD Ryzen 9 7950X3D 16-Core Processor | 5400 | 32 | 71566 | 1566279 | system |
|AMD Ryzen 9 7950X3D 16-Core Processor | 5478 | 32 | 161960 | 2173959 | both |

View File

@ -418,3 +418,7 @@
{"config": {"afl_persistent_config": true, "afl_system_config": true, "afl_version": "++4.08a", "comment": "", "compiler": "Ubuntu clang version 14.0.0-1ubuntu1.1", "target_arch": "x86_64-pc-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 3700.0, "cpu_model": "AMD Ryzen 5 PRO 4650G with Radeon Graphics", "cpu_threads": 12}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 704840.16, "execs_total": 21163992, "fuzzers_used": 12}, "singlecore": {"execs_per_sec": 95356.14, "execs_total": 2862114, "fuzzers_used": 1}}}}
{"config": {"afl_persistent_config": true, "afl_system_config": true, "afl_version": "++4.09a", "comment": "", "compiler": "Debian clang version 14.0.6", "target_arch": "aarch64-unknown-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 2400.0, "cpu_model": "Raspberry Pi 5", "cpu_threads": 4}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 101114.23, "execs_total": 3036637, "fuzzers_used": 4}, "singlecore": {"execs_per_sec": 25786.11, "execs_total": 774460, "fuzzers_used": 1}}}}
{"config": {"afl_persistent_config": true, "afl_system_config": true, "afl_version": "++4.07a", "comment": "", "compiler": "Debian clang version 17.0.0 (++20230417071830+ae77aceba5ad-1~exp1~20230417071935.630)", "target_arch": "x86_64-pc-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 4792.073, "cpu_model": "AMD Ryzen 9 5950X 16-Core Processor", "cpu_threads": 32}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 2339762.91, "execs_total": 70253164, "fuzzers_used": 32}, "singlecore": {"execs_per_sec": 161690.07, "execs_total": 4851838, "fuzzers_used": 1}}}}
{"config": {"afl_persistent_config": false, "afl_system_config": true, "afl_version": "++4.10c", "comment": "", "compiler": "clang version 17.0.6", "target_arch": "x86_64-pc-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 4675.949, "cpu_model": "AMD Ryzen 9 6900HS with Radeon Graphics", "cpu_threads": 16}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 614403.91, "execs_total": 18435083, "fuzzers_used": 16}, "singlecore": {"execs_per_sec": 62859.9, "execs_total": 1886111, "fuzzers_used": 1}}}}
{"config": {"afl_persistent_config": true, "afl_system_config": true, "afl_version": "++4.10c", "comment": "", "compiler": "clang version 17.0.6", "target_arch": "x86_64-pc-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 4744.522, "cpu_model": "AMD Ryzen 9 6900HS with Radeon Graphics", "cpu_threads": 16}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 991132.96, "execs_total": 29737588, "fuzzers_used": 16}, "singlecore": {"execs_per_sec": 135501.07, "execs_total": 4066116, "fuzzers_used": 1}}}}
{"config": {"afl_persistent_config": false, "afl_system_config": true, "afl_version": "++4.10c", "comment": "", "compiler": "Ubuntu clang version 14.0.6", "target_arch": "x86_64-pc-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 5399.822, "cpu_model": "AMD Ryzen 9 7950X3D 16-Core Processor", "cpu_threads": 32}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 1566279.42, "execs_total": 46994452, "fuzzers_used": 32}, "singlecore": {"execs_per_sec": 71565.56, "execs_total": 2147396, "fuzzers_used": 1}}}}
{"config": {"afl_persistent_config": true, "afl_system_config": true, "afl_version": "++4.10c", "comment": "", "compiler": "clang version 17.0.6", "target_arch": "x86_64-pc-linux-gnu"}, "hardware": {"cpu_fastest_core_mhz": 5478.258, "cpu_model": "AMD Ryzen 9 7950X3D 16-Core Processor", "cpu_threads": 32}, "targets": {"test-instr-persist-shmem": {"multicore": {"execs_per_sec": 2173959.15, "execs_total": 65229513, "fuzzers_used": 32}, "singlecore": {"execs_per_sec": 161960.29, "execs_total": 4859457, "fuzzers_used": 1}}}}

View File

@ -205,7 +205,7 @@ async def save_benchmark_results() -> None:
single = str(round(results.targets["test-instr-persist-shmem"]["singlecore"].execs_per_sec)).ljust(10)
multi = str(round(results.targets["test-instr-persist-shmem"]["multicore"].execs_per_sec)).ljust(9)
cores = str(args.fuzzers).ljust(7)
comparisonfile.write(f"{cpu_model} | {cpu_mhz} | {cores} | {single} | {multi} | {aflconfig} |\n")
comparisonfile.write(f"|{cpu_model} | {cpu_mhz} | {cores} | {single} | {multi} | {aflconfig} |\n")
print(blue(f" [*] Results have been written to the COMPARISON.md file."))
with open("COMPARISON.md", "r") as comparisonfile:
print(comparisonfile.read())

View File

@ -1,3 +1,4 @@
#include "afl-fuzz.h"
#include "afl-mutations.h"
typedef struct my_mutator {

View File

@ -1,9 +1,6 @@
#include "afl-fuzz.h"
#include "afl-mutations.h"
s8 interesting_8[] = {INTERESTING_8};
s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
typedef struct my_mutator {
afl_state_t *afl;
@ -155,7 +152,7 @@ int main(int argc, char *argv[]) {
return -1;
}
if (verbose) fprintf(stderr, "Mutation output length: %zu\n", outlen);
if (verbose) fprintf(stderr, "Mutation output length: %u\n", outlen);
if (fwrite(outbuf, 1, outlen, out) != outlen) {
fprintf(stderr, "Warning: incomplete write.\n");

View File

@ -1 +1 @@
5ed4f8d
95a6857

View File

@ -187,8 +187,8 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
DBG("test=%s\n", fn);
if (stat(source_name, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
u8 *destination_name =
alloc_printf("%s/%s.%s", data->out_dir, origin_name, nl[i]->d_name);
u8 *destination_name = alloc_printf("%s/%s.%s", data->out_dir,
origin_name, nl[i]->d_name);
rename(source_name, destination_name);
ck_free(destination_name);
DBG("found=%s\n", source_name);
@ -282,13 +282,13 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
if (items <= 0) return 0;
for (i = 0; i < (u32)items; ++i) {
for (i = 0; i < (s32)items; ++i) {
if (!done) {
struct stat st;
u8 *fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
if (done == 0) {
if (stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
int fd = open(fn, O_RDONLY);
@ -306,10 +306,10 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
}
unlink(fn);
ck_free(fn);
}
ck_free(fn);
free(nl[i]);
}

View File

@ -3,6 +3,78 @@
This is the list of all noteworthy changes made in every public
release of the tool. See README.md for the general instruction manual.
### Version ++4.21a (dev)
* afl-fuzz
- fixed a regression in afl-fuzz that resulted in a 5-10% performace loss
do a switch from gettimeofday() to clock_gettime() which should be rather
three times faster. The reason for this is unknown.
- added AFL_DISABLE_REDUNDANT for huge queues
- fix AFL_PERSISTENT_RECORD
- run custom_post_process after standard trimming
- prevent filenames in the queue that have spaces
- minor fix for FAST schedules
- more frequent stats update when syncing (todo: check performance impact)
- now timing of calibration, trimming and syncing is measured seperately,
thanks to @eqv!
- -V timing is now accurately the fuzz time (without syncing), before
long calibration times and syncing could result in now fuzzing being
made when the time was already run out until then, thanks to @eqv!
* afl-cc:
- re-enable i386 support that was accidently disabled
- fixes for LTO and outdated afl-gcc mode for i386
- fix COMPCOV split compare for old LLVMs
- disable xml/curl/g_ string transform functions because we do not check
for null pointers ... TODO
- ensure shared memory variables are visible in weird build setups
- compatability to new LLVM 19 changes
* afl-cmin
- work with input files that have a space
* afl-showmap
- fix memory leak on shmem testcase usage (thanks to @ndrewh)
- minor fix to collect coverage -C (thanks to @bet4it)
* enhanced the ASAN configuration
### Version ++4.20c (release)
! A new forkserver communication model is now introduced. afl-fuzz is
backward compatible to old compiled targets if they are not built
for CMPLOG/Redqueen, but new compiled targets will not work with
old afl-fuzz versions!
! Recompile all targets that are instrumented for CMPLOG/Redqueen!
- AFL++ now supports up to 4 billion coverage edges, up from 6 million.
- New compile option: `make PERFORMANCE=1` - this will enable special
CPU dependent optimizations that make everything more performant - but
the binaries will likely won't work on different platforms. Also
enables a faster hasher if the CPU requirements are met.
- The persistent record feature (see config.h) was expanded to also
support replay, thanks to @quarta-qti !
- afl-fuzz:
- the new deterministic fuzzing feature is now activated by default,
deactivate with -z. Parameters -d and -D are ignored.
- small improvements to CMPLOG/redqueen
- workround for a bug with MOpt -L when used with -M - in the future
we will either remove or rewrite MOpt.
- fix for `-t xxx+` feature
- -e extension option now saves the queue items, crashes, etc. with the
extension too
- fixes for trimmming, correct -V time and reading stats on resume by eqv
thanks a lot!
- afl-cc:
- added collision free caller instrumentation to LTO mode. activate with
`AFL_LLVM_LTO_CALLER=1`. You can set a max depth to go through single
block functions with `AFL_LLVM_LTO_CALLER_DEPTH` (default 0)
- fixes for COMPCOV/LAF and most other modules
- fix for GCC_PLUGIN cmplog that broke on std::strings
- afl-whatsup:
- now also displays current average speed
- small bugfixes
- custom mutators:
- fixes for aflpp custom mutator and standalone tool
- important fix to the symcc custom mutator
- Minor edits to afl-persistent-config
- Prevent temporary files being left behind on aborted afl-whatsup
- More CPU benchmarks added to benchmark/
### Version ++4.10c (release)
- afl-fuzz:
- default power schedule is now EXPLORE, due a fix in fast schedules

View File

@ -21,7 +21,7 @@ If you want to build AFL++ yourself, you have many options. The easiest choice
is to build and install everything:
NOTE: depending on your Debian/Ubuntu/Kali/... release, replace `-14` with
whatever llvm version is available. We recommend llvm 13, 14, 15 or 16.
whatever llvm version is available. We recommend llvm 13 or newer.
```shell
sudo apt-get update
@ -67,19 +67,20 @@ These build targets exist:
* unit: perform unit tests (based on cmocka)
* help: shows these build options
[Unless you are on Mac OS X](https://developer.apple.com/library/archive/qa/qa1118/_index.html),
[Unless you are on macOS](https://developer.apple.com/library/archive/qa/qa1118/_index.html),
you can also build statically linked versions of the AFL++ binaries by passing
the `STATIC=1` argument to make:
the `PERFORMANCE=1` argument to make:
```shell
make STATIC=1
make PERFORMANCE=1
```
These build options exist:
* STATIC - compile AFL++ static
* CODE_COVERAGE - compile the target for code coverage (see docs/instrumentation/README.llvm.md)
* ASAN_BUILD - compiles AFL++ with memory sanitizer for debug purposes
* PERFORMANCE - compile with performance options that make the binary not transferable to other systems. Recommended (except on macOS)!
* STATIC - compile AFL++ static (does not work on macOS)
* CODE_COVERAGE - compile the target for code coverage (see [README.llvm.md](../instrumentation/README.llvm.md))
* ASAN_BUILD - compiles AFL++ with address sanitizer for debug purposes
* UBSAN_BUILD - compiles AFL++ tools with undefined behaviour sanitizer for debug purposes
* DEBUG - no optimization, -ggdb3, all warnings and -Werror
* LLVM_DEBUG - shows llvm deprecation warnings
@ -91,101 +92,78 @@ These build options exist:
* NO_NYX - disable building nyx mode dependencies
* NO_CORESIGHT - disable building coresight (arm64 only)
* NO_UNICORN_ARM64 - disable building unicorn on arm64
* AFL_NO_X86 - if compiling on non-intel/amd platforms
* AFL_NO_X86 - if compiling on non-Intel/AMD platforms
* LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config (e.g., Debian)
e.g.: `make LLVM_CONFIG=llvm-config-14`
## MacOS X on x86 and arm64 (M1)
## macOS on x86_64 and arm64
MacOS has some gotchas due to the idiosyncrasies of the platform.
macOS has some gotchas due to the idiosyncrasies of the platform.
To build AFL, install llvm (and perhaps gcc) from brew and follow the general
instructions for Linux. If possible, avoid Xcode at all cost.
macOS supports SYSV shared memory used by AFL++'s instrumentation, but the
default settings aren't sufficient. Before even building, increase
them by running the provided script:
```shell
sudo afl-system-config
```
See
[https://www.spy-hill.com/help/apple/SharedMemory.html](https://www.spy-hill.com/help/apple/SharedMemory.html)
for documentation for the shared memory settings and how to make them permanent.
Next, to build AFL++, install the following packages from brew:
```shell
brew install wget git make cmake llvm gdb coreutils
```
Be sure to setup `PATH` to point to the correct clang binaries and use the
freshly installed clang, clang++, llvm-config, gmake and coreutils, e.g.:
Depending on your macOS system + brew version, brew may be installed in different places.
You can check with `brew info llvm` to know where, then create a variable for it:
```shell
# Depending on your MacOS system + brew version it is either
export PATH="/opt/homebrew/opt/llvm/bin:$PATH"
# or
export PATH="/usr/local/opt/llvm/bin:/usr/local/opt/coreutils/libexec/gnubin:$PATH"
# you can check with "brew info llvm"
export HOMEBREW_BASE="/opt/homebrew/opt"
```
export PATH="/usr/local/bin:$PATH"
or
```shell
export HOMEBREW_BASE="/usr/local/opt"
```
Set `PATH` to point to the brew clang, clang++, llvm-config, gmake and coreutils.
Also use the brew clang compiler; the Xcode clang compiler must not be used.
```shell
export PATH="$HOMEBREW_BASE/coreutils/libexec/gnubin:/usr/local/bin:$HOMEBREW_BASE/llvm/bin:$PATH"
export CC=clang
export CXX=clang++
gmake
cd frida_mode
gmake
cd ..
sudo gmake install
```
`afl-gcc` will fail unless you have GCC installed, but that is using outdated
instrumentation anyway. `afl-clang` might fail too depending on your PATH setup.
But you don't want neither, you want `afl-clang-fast` anyway :) Note that
`afl-clang-lto`, `afl-gcc-fast` and `qemu_mode` are not working on MacOS.
Then build following the general Linux instructions.
The crash reporting daemon that comes by default with MacOS X will cause
problems with fuzzing. You need to turn it off:
If everything worked, you should then have `afl-clang-fast` installed, which you can check with:
```
launchctl unload -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist
```shell
which afl-clang-fast
```
The `fork()` semantics on OS X are a bit unusual compared to other unix systems
Note that `afl-clang-lto`, `afl-gcc-fast` and `qemu_mode` are not working on macOS.
The crash reporting daemon that comes by default with macOS will cause
problems with fuzzing. You need to turn it off, which you can do with `afl-system-config`.
The `fork()` semantics on macOS are a bit unusual compared to other unix systems
and definitely don't look POSIX-compliant. This means two things:
- Fuzzing will be probably slower than on Linux. In fact, some folks report
considerable performance gains by running the jobs inside a Linux VM on
MacOS X.
macOS.
- Some non-portable, platform-specific code may be incompatible with the AFL++
forkserver. If you run into any problems, set `AFL_NO_FORKSRV=1` in the
environment before starting afl-fuzz.
User emulation mode of QEMU does not appear to be supported on MacOS X, so
User emulation mode of QEMU does not appear to be supported on macOS, so
black-box instrumentation mode (`-Q`) will not work. However, FRIDA mode (`-O`)
works on both x86 and arm64 MacOS boxes.
MacOS X supports SYSV shared memory used by AFL's instrumentation, but the
default settings aren't usable with AFL++. The default settings on 10.14 seem to
be:
```bash
$ ipcs -M
IPC status from <running system> as of XXX
shminfo:
shmmax: 4194304 (max shared memory segment size)
shmmin: 1 (min shared memory segment size)
shmmni: 32 (max number of shared memory identifiers)
shmseg: 8 (max shared memory segments per process)
shmall: 1024 (max amount of shared memory in pages)
```
To temporarily change your settings to something minimally usable with AFL++,
run these commands as root:
```bash
sysctl kern.sysv.shmmax=8388608
sysctl kern.sysv.shmall=4096
```
If you're running more than one instance of AFL, you likely want to make
`shmall` bigger and increase `shmseg` as well:
```bash
sysctl kern.sysv.shmmax=8388608
sysctl kern.sysv.shmseg=48
sysctl kern.sysv.shmall=98304
```
See
[http://www.spy-hill.com/help/apple/SharedMemory.html](http://www.spy-hill.com/help/apple/SharedMemory.html)
for documentation for these settings and how to make them permanent.
works on both x86 and arm64 macOS boxes.

View File

@ -266,6 +266,11 @@ trimmed input. Here's a quick API description:
Omitting any of three trimming methods will cause the trimming to be disabled
and trigger a fallback to the built-in default trimming routine.
**IMPORTANT** If you have a custom post process mutator that needs to be run
after trimming, you must call it yourself at the end of your successful
trimming!
### Environment Variables
Optionally, the following environment variables are supported:

View File

@ -248,6 +248,9 @@ use (which only ever the author of this LTO implementation will use). These are
used if several separated instrumentations are performed which are then later
combined.
- `AFL_LLVM_LTO_CALLER` activates collision free CALLER instrumentation
- `AFL_LLVM_LTO_CALLER` sets the maximum mumber of single block functions
to dig deeper into a real function. Default 0.
- `AFL_LLVM_DOCUMENT_IDS=file` will document to a file which edge ID was given
to which function. This helps to identify functions with variable bytes or
which functions were touched by an input.
@ -378,6 +381,9 @@ checks or alter some of the more exotic semantics of the tool:
- Setting `AFL_DISABLE_TRIM` tells afl-fuzz not to trim test cases. This is
usually a bad idea!
- Setting `AFL_DISABLE_REDUNDANT` disables any queue items that are redundant.
This can be useful with huge queues.
- Setting `AFL_KEEP_TIMEOUTS` will keep longer running inputs if they reach
new coverage
@ -544,6 +550,9 @@ checks or alter some of the more exotic semantics of the tool:
use a custom afl-qemu-trace or if you need to modify the afl-qemu-trace
arguments.
- `AFL_SHA1_FILENAMES` causes AFL++ to generate files named by the SHA1 hash
of their contents, rather than use the standard `id:000000,...` names.
- `AFL_SHUFFLE_QUEUE` randomly reorders the input queue on startup. Requested
by some users for unorthodox parallelized fuzzing setups, but not advisable
otherwise.

View File

@ -958,7 +958,7 @@ too long for your overall available fuzz run time.
campaign but not good for short CI runs.
How this can look like can, e.g., be seen at AFL++'s setup in Google's
[oss-fuzz](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/compile_afl)
[previous oss-fuzz version](https://github.com/google/oss-fuzz/blob/3e2c5312417d1a6f9564472f3df1fd27759b289d/infra/base-images/base-builder/compile_afl)
and
[clusterfuzz](https://github.com/google/clusterfuzz/blob/master/src/clusterfuzz/_internal/bot/fuzzers/afl/launcher.py).

View File

@ -5,6 +5,10 @@
* [afl-rs](https://github.com/rust-fuzz/afl.rs) - AFL++ for RUST
* [WASM](https://github.com/fgsect/WAFL) - AFL++ for WASM
## Starting multiple AFL++ instances in parallel with recommended settings:
* [https://github.com/0xricksanchez/AFL_Runner](https://github.com/0xricksanchez/AFL_Runner)
* [https://github.com/MegaManSec/AFLplusplus-Parallel-Gen](https://github.com/MegaManSec/AFLplusplus-Parallel-Gen)
## Speeding up fuzzing
* [libfiowrapper](https://github.com/marekzmyslowski/libfiowrapper) - if the

View File

@ -21,6 +21,9 @@ training, then we can highly recommend the following:
* [https://github.com/antonio-morales/Fuzzing101](https://github.com/antonio-morales/Fuzzing101)
A good workflow overview (like our [fuzzing_in_depth.md](fuzzing_in_depth.md)):
* [https://appsec.guide/docs/fuzzing/c-cpp/aflpp/](https://appsec.guide/docs/fuzzing/c-cpp/aflpp/)
Here is a good workflow description (and tutorial) for qemu_mode:
* [https://airbus-seclab.github.io/AFLplusplus-blogpost/](https://airbus-seclab.github.io/AFLplusplus-blogpost/)

View File

@ -2,7 +2,7 @@
test -n "$1" && { echo This script has no options. It updates the referenced Frida version in GNUmakefile to the most current one. ; exit 1 ; }
OLD=$(grep -E '^GUM_DEVKIT_VERSION=' GNUmakefile 2>/dev/null|awk -F= '{print$2}')
NEW=$(curl https://github.com/frida/frida/releases/ 2>/dev/null|grep -E 'frida-gum-devkit-[0-9.]*-linux-x86_64'|head -n 1|sed 's/.*frida-gum-devkit-//'|sed 's/-linux.*//')
NEW=$(curl https://github.com/frida/frida/releases/ 2>/dev/null|grep 'Frida\ [0-9.]*'|head -n 1|sed 's/.*Frida\ //'| sed 's/<\/h2>//')
echo Current set version: $OLD
echo Newest available version: $NEW

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>

View File

@ -5,9 +5,9 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>
Dominik Maier <mail@dmnk.co>,
Andrea Fioraldi <andreafioraldi@gmail.com>, and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>
Copyright 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
@ -124,6 +124,10 @@
#define CASE_PREFIX "id_"
#endif /* ^!SIMPLE_FILES */
#ifdef AFL_PERSISTENT_RECORD
#define RECORD_PREFIX "RECORD:"
#endif
#define STAGE_BUF_SIZE (64) /* usable size for stage name buf in afl_state */
// Little helper to access the ptr to afl->##name_buf - for use in afl_realloc.
@ -135,6 +139,10 @@
#define AFL_RAND_RETURN u32
#endif
#ifndef INTERESTING_32_LEN
#error INTERESTING_32_LEN not defined - BUG!
#endif
extern s8 interesting_8[INTERESTING_8_LEN];
extern s16 interesting_16[INTERESTING_8_LEN + INTERESTING_16_LEN];
extern s32
@ -448,7 +456,8 @@ typedef struct afl_env_vars {
afl_keep_timeouts, afl_no_crash_readme, afl_ignore_timeouts,
afl_no_startup_calibration, afl_no_warn_instability,
afl_post_process_keep_original, afl_crashing_seeds_as_new_crash,
afl_final_sync, afl_ignore_seed_problems;
afl_final_sync, afl_ignore_seed_problems, afl_disable_redundant,
afl_sha1_filenames;
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload,
@ -644,7 +653,10 @@ typedef struct afl_state {
longest_find_time, /* Longest time taken for a find */
exit_on_time, /* Delay to exit if no new paths */
sync_time, /* Sync time (ms) */
switch_fuzz_mode; /* auto or fixed fuzz mode */
switch_fuzz_mode, /* auto or fixed fuzz mode */
calibration_time_us, /* Time spend on calibration */
sync_time_us, /* Time spend on sync */
trim_time_us; /* Time spend on trimming */
u32 slowest_exec_ms, /* Slowest testcase non hang in ms */
subseq_tmouts; /* Number of timeouts in a row */
@ -1211,6 +1223,10 @@ void show_stats_normal(afl_state_t *);
void show_stats_pizza(afl_state_t *);
void show_init_stats(afl_state_t *);
void update_calibration_time(afl_state_t *afl, u64 *time);
void update_trim_time(afl_state_t *afl, u64 *time);
void update_sync_time(afl_state_t *afl, u64 *time);
/* StatsD */
void statsd_setup_format(afl_state_t *afl);
@ -1393,6 +1409,32 @@ void queue_testcase_retake_mem(afl_state_t *afl, struct queue_entry *q, u8 *in,
void queue_testcase_store_mem(afl_state_t *afl, struct queue_entry *q, u8 *mem);
/* Compute the SHA1 hash of `data`, which is of `len` bytes, and return the
* result as a `\0`-terminated hex string, which the caller much `ck_free`. */
char *sha1_hex(const u8 *data, size_t len);
/* Apply `sha1_hex` to the first `len` bytes of data of the file at `fname`. */
char *sha1_hex_for_file(const char *fname, u32 len);
/* Create file `fn`, but allow it to already exist if `AFL_SHA1_FILENAMES` is
* enabled. */
static inline int permissive_create(afl_state_t *afl, const char *fn) {
int fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (unlikely(fd < 0)) {
if (!(afl->afl_env.afl_sha1_filenames && errno == EEXIST)) {
PFATAL("Unable to create '%s'", fn);
}
}
return fd;
}
#if TESTCASE_CACHE == 1
#error define of TESTCASE_CACHE must be zero or larger than 1
#endif

View File

@ -30,10 +30,17 @@
#include <stdbool.h>
#include <inttypes.h>
#include "afl-fuzz.h"
#define MUT_STRATEGY_ARRAY_SIZE 256
#ifndef INTERESTING_32
#error INTERESTING_32 is not defined - BUG!
#endif
s8 interesting_8[] = {INTERESTING_8};
s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
enum {
/* 00 */ MUT_FLIPBIT,

View File

@ -0,0 +1,131 @@
#ifndef _HAVE_PERSISTENT_REPLAY_H
#define _HAVE_PERSISTENT_REPLAY_H
#include <dirent.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
static unsigned short int is_replay_record;
static unsigned int replay_record;
static unsigned int replay_record_cnt;
static char replay_record_path[PATH_MAX];
static char *replay_record_dir;
static struct dirent **record_list;
#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE
static char **record_arg = NULL;
#endif // AFL_PERSISTENT_REPLAY_ARGPARSE
static int select_files(const struct dirent *dirbuf) {
char fn[PATH_MAX];
if (dirbuf->d_name[0] == '.') {
return 0;
} else {
snprintf(fn, sizeof(fn), "RECORD:%06u", replay_record);
return !!strstr(dirbuf->d_name, fn);
}
}
static int compare_files(const struct dirent **da, const struct dirent **db) {
unsigned int c1 = 0, c2 = 0;
sscanf((*da)->d_name, "RECORD:%*u,cnt:%06u", &c1);
sscanf((*db)->d_name, "RECORD:%*u,cnt:%06u", &c2);
return c1 - c2;
}
__attribute__((destructor)) static void __afl_record_replay_destroy(void) {
for (int i = 0; i < replay_record_cnt; i++) {
free(record_list[i]);
}
free(record_list);
}
__attribute__((constructor)) static void __afl_record_replay_init(
#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE
int argc, char **argv
#endif // AFL_PERSISTENT_REPLAY_ARGPARSE
) {
#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE
char **argp;
#endif // AFL_PERSISTENT_REPLAY_ARGPARSE
struct stat sb;
/* caveat: if harness uses @@ and we don't pass it, it will regardless loop
* the number of iterations defined for AFL_LOOP (on the same file)*/
if (!(is_replay_record = !!getenv("AFL_PERSISTENT_REPLAY"))) {
// printf("[warning] AFL_PERSISTENT_REPLAY not set.\n");
return;
}
replay_record = atoi(getenv("AFL_PERSISTENT_REPLAY"));
replay_record_dir = getenv("AFL_PERSISTENT_DIR");
if (!(stat(replay_record_dir, &sb) == 0 && S_ISDIR(sb.st_mode))) {
fprintf(stderr, "[error] Can't find the requested record directory!\n");
is_replay_record = 0;
return;
}
replay_record_cnt = scandir(replay_record_dir ? replay_record_dir : "./",
&record_list, select_files, compare_files);
if (!replay_record_cnt) {
fprintf(stderr, "[error] Can't find the requested record!\n");
is_replay_record = 0;
}
#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE
argp = argv;
while (*argp) {
if (!strcmp(*argp, "@@")) {
record_arg = argp;
*record_arg = replay_record_path;
break;
}
++argp;
}
#endif // AFL_PERSISTENT_REPLAY_ARGPARSE
}
#endif // _HAVE_PERSISTENT_REPLAY_H

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>

View File

@ -0,0 +1,67 @@
#ifndef _HAVE_AFL_COMPAT_H
#define _HAVE_AFL_COMPAT_H
#include <afl-persistent-replay.h>
#define FUZZ_BUF_SIZE 1024000
// extern ssize_t read(int fildes, void *buf, size_t nbyte);
// extern int __afl_persistent_loop(unsigned int max_cnt);
// extern unsigned char fuzz_buf[];
#ifndef __AFL_HAVE_MANUAL_CONTROL
#define __AFL_HAVE_MANUAL_CONTROL
#endif
#define __AFL_FUZZ_TESTCASE_LEN (read(0, fuzz_buf, FUZZ_BUF_SIZE))
#define __AFL_FUZZ_TESTCASE_BUF fuzz_buf
#define __AFL_FUZZ_INIT() void sync(void);
#define __AFL_INIT() sync()
#define __AFL_LOOP(x) __afl_persistent_loop(x)
unsigned char fuzz_buf[FUZZ_BUF_SIZE];
int __afl_persistent_loop(unsigned int max_cnt) {
static unsigned int cycle_cnt = 1;
static unsigned short int inited = 0;
char tcase[PATH_MAX];
if (is_replay_record && cycle_cnt) {
if (!inited) {
cycle_cnt = replay_record_cnt;
inited = 1;
}
snprintf(tcase, PATH_MAX, "%s/%s",
replay_record_dir ? replay_record_dir : "./",
record_list[replay_record_cnt - cycle_cnt]->d_name);
#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE
if (record_arg) {
*record_arg = tcase;
} else
#endif // AFL_PERSISTENT_REPLAY_ARGPARSE
{
int fd = open(tcase, O_RDONLY);
dup2(fd, 0);
close(fd);
}
}
return cycle_cnt--;
}
#endif // _HAVE_AFL_COMPAT_H

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>
@ -38,18 +38,15 @@
#define SHAPE_BYTES(x) (x + 1)
#define CMP_TYPE_INS 1
#define CMP_TYPE_RTN 2
#define CMP_TYPE_INS 0
#define CMP_TYPE_RTN 1
struct cmp_header {
struct cmp_header { // 16 bit = 2 bytes
unsigned hits : 24;
unsigned id : 24;
unsigned shape : 5;
unsigned type : 2;
unsigned attribute : 4;
unsigned overflow : 1;
unsigned reserved : 4;
unsigned hits : 6; // up to 63 entries, we have CMP_MAP_H = 32
unsigned shape : 5; // 31+1 bytes max
unsigned type : 1; // 2: cmp, rtn
unsigned attribute : 4; // 16 for arithmetic comparison types
} __attribute__((packed));
@ -59,14 +56,17 @@ struct cmp_operands {
u64 v1;
u64 v0_128;
u64 v1_128;
u64 unused;
u8 unused1;
u8 unused2;
} __attribute__((packed));
struct cmpfn_operands {
u8 v0[31];
u8 v0[32];
u8 v0_len;
u8 v1[31];
u8 v1[32];
u8 v1_len;
} __attribute__((packed));

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>

View File

@ -26,7 +26,7 @@
/* Version string: */
// c = release, a = volatile github dev, e = experimental branch
#define VERSION "++4.10c"
#define VERSION "++4.21a"
/******************************************************
* *
@ -97,6 +97,11 @@
// #define AFL_PERSISTENT_RECORD
/* Adds support in compiler-rt to replay persistent records in @@-style
* harnesses */
// #define AFL_PERSISTENT_REPLAY_ARGPARSE
/* console output colors: There are three ways to configure its behavior
* 1. default: colored outputs fixed on: defined USE_COLOR && defined
* ALWAYS_COLORED The env var. AFL_NO_COLOR will have no effect
@ -459,7 +464,7 @@
/* Do not change this unless you really know what you are doing. */
#define MAP_SIZE (1U << MAP_SIZE_POW2)
#if MAP_SIZE <= 65536
#if MAP_SIZE <= 2097152
#define MAP_INITIAL_SIZE (2 << 20) // = 2097152
#else
#define MAP_INITIAL_SIZE MAP_SIZE

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>

View File

@ -21,17 +21,18 @@ static char *afl_environment_variables[] = {
"AFL_BENCH_UNTIL_CRASH", "AFL_CAL_FAST", "AFL_CC", "AFL_CC_COMPILER",
"AFL_CMIN_ALLOW_ANY", "AFL_CMIN_CRASHES_ONLY", "AFL_CMPLOG_ONLY_NEW",
"AFL_CODE_END", "AFL_CODE_START", "AFL_COMPCOV_BINNAME",
"AFL_COMPCOV_LEVEL", "AFL_CRASH_EXITCODE",
"AFL_CRASHING_SEEDS_AS_NEW_CRASH", "AFL_CUSTOM_MUTATOR_LIBRARY",
"AFL_CUSTOM_MUTATOR_ONLY", "AFL_CUSTOM_INFO_PROGRAM",
"AFL_CUSTOM_INFO_PROGRAM_ARGV", "AFL_CUSTOM_INFO_PROGRAM_INPUT",
"AFL_CUSTOM_INFO_OUT", "AFL_CXX", "AFL_CYCLE_SCHEDULES", "AFL_DEBUG",
"AFL_DEBUG_CHILD", "AFL_DEBUG_GDB", "AFL_DEBUG_UNICORN", "AFL_DISABLE_TRIM",
"AFL_DISABLE_LLVM_INSTRUMENTATION", "AFL_DONT_OPTIMIZE",
"AFL_DRIVER_STDERR_DUPLICATE_FILENAME", "AFL_DUMB_FORKSRV",
"AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT", "AFL_EXIT_WHEN_DONE",
"AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES", "AFL_FAST_CAL",
"AFL_FINAL_SYNC", "AFL_FORCE_UI", "AFL_FRIDA_DEBUG_MAPS",
"AFL_DUMP_CYCLOMATIC_COMPLEXITY", "AFL_CMPLOG_MAX_LEN", "AFL_COMPCOV_LEVEL",
"AFL_CRASH_EXITCODE", "AFL_CRASHING_SEEDS_AS_NEW_CRASH",
"AFL_CUSTOM_MUTATOR_LIBRARY", "AFL_CUSTOM_MUTATOR_ONLY",
"AFL_CUSTOM_INFO_PROGRAM", "AFL_CUSTOM_INFO_PROGRAM_ARGV",
"AFL_CUSTOM_INFO_PROGRAM_INPUT", "AFL_CUSTOM_INFO_OUT", "AFL_CXX",
"AFL_CYCLE_SCHEDULES", "AFL_DEBUG", "AFL_DEBUG_CHILD", "AFL_DEBUG_GDB",
"AFL_DEBUG_UNICORN", "AFL_DISABLE_REDUNDANT", "AFL_NO_REDUNDANT",
"AFL_DISABLE_TRIM", "AFL_NO_TRIM", "AFL_DISABLE_LLVM_INSTRUMENTATION",
"AFL_DONT_OPTIMIZE", "AFL_DRIVER_STDERR_DUPLICATE_FILENAME",
"AFL_DUMB_FORKSRV", "AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT",
"AFL_EXIT_WHEN_DONE", "AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES",
"AFL_FAST_CAL", "AFL_FINAL_SYNC", "AFL_FORCE_UI", "AFL_FRIDA_DEBUG_MAPS",
"AFL_FRIDA_DRIVER_NO_HOOK", "AFL_FRIDA_EXCLUDE_RANGES",
"AFL_FRIDA_INST_CACHE_SIZE", "AFL_FRIDA_INST_COVERAGE_ABSOLUTE",
"AFL_FRIDA_INST_COVERAGE_FILE", "AFL_FRIDA_INST_DEBUG_FILE",
@ -64,6 +65,8 @@ static char *afl_environment_variables[] = {
"AFL_REAL_LD", "AFL_LD_PRELOAD", "AFL_LD_VERBOSE", "AFL_LLVM_ALLOWLIST",
"AFL_LLVM_DENYLIST", "AFL_LLVM_BLOCKLIST", "AFL_CMPLOG", "AFL_LLVM_CMPLOG",
"AFL_GCC_CMPLOG", "AFL_LLVM_INSTRIM", "AFL_LLVM_CALLER", "AFL_LLVM_CTX",
"AFL_LLVM_LTO_CALLER", "AFL_LLVM_LTO_CTX", "AFL_LLVM_LTO_CALLER_DEPTH",
"AFL_LLVM_LTO_CTX_DEPTH", "AFL_LLVM_CALLER_DEPTH", "AFL_LLVM_CTX_DEPTH",
"AFL_LLVM_CTX_K", "AFL_LLVM_DICT2FILE", "AFL_LLVM_DICT2FILE_NO_MAIN",
"AFL_LLVM_DOCUMENT_IDS", "AFL_LLVM_INSTRIM_LOOPHEAD", "AFL_LLVM_INSTRUMENT",
"AFL_LLVM_LTO_AUTODICTIONARY", "AFL_LLVM_AUTODICTIONARY",
@ -93,27 +96,27 @@ static char *afl_environment_variables[] = {
"AFL_MAX_DET_EXTRAS",
"AFL_NO_X86", // not really an env but we dont want to warn on it
"AFL_NOOPT", "AFL_NYX_AUX_SIZE", "AFL_NYX_DISABLE_SNAPSHOT_MODE",
"AFL_NYX_LOG", "AFL_NYX_REUSE_SNAPSHOT", "AFL_PASSTHROUGH", "AFL_PATH",
"AFL_PERFORMANCE_FILE", "AFL_PERSISTENT_RECORD",
"AFL_POST_PROCESS_KEEP_ORIGINAL", "AFL_PRELOAD", "AFL_TARGET_ENV",
"AFL_PYTHON_MODULE", "AFL_QEMU_CUSTOM_BIN", "AFL_QEMU_COMPCOV",
"AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_DEBUG_MAPS", "AFL_QEMU_DISABLE_CACHE",
"AFL_QEMU_DRIVER_NO_HOOK", "AFL_QEMU_FORCE_DFL", "AFL_QEMU_PERSISTENT_ADDR",
"AFL_QEMU_PERSISTENT_CNT", "AFL_QEMU_PERSISTENT_GPR",
"AFL_QEMU_PERSISTENT_HOOK", "AFL_QEMU_PERSISTENT_MEM",
"AFL_QEMU_PERSISTENT_RET", "AFL_QEMU_PERSISTENT_RETADDR_OFFSET",
"AFL_QEMU_PERSISTENT_EXITS", "AFL_QEMU_INST_RANGES",
"AFL_QEMU_EXCLUDE_RANGES", "AFL_QEMU_SNAPSHOT", "AFL_QEMU_TRACK_UNSTABLE",
"AFL_QUIET", "AFL_RANDOM_ALLOC_CANARY", "AFL_REAL_PATH",
"AFL_SHUFFLE_QUEUE", "AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ",
"AFL_SKIP_CRASHES", "AFL_SKIP_OSSFUZZ", "AFL_STATSD", "AFL_STATSD_HOST",
"AFL_STATSD_PORT", "AFL_STATSD_TAGS_FLAVOR", "AFL_SYNC_TIME",
"AFL_TESTCACHE_SIZE", "AFL_TESTCACHE_ENTRIES", "AFL_TMIN_EXACT",
"AFL_TMPDIR", "AFL_TOKEN_FILE", "AFL_TRACE_PC", "AFL_USE_ASAN",
"AFL_USE_MSAN", "AFL_USE_TRACE_PC", "AFL_USE_UBSAN", "AFL_USE_TSAN",
"AFL_USE_CFISAN", "AFL_USE_LSAN", "AFL_WINE_PATH", "AFL_NO_SNAPSHOT",
"AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", "AFL_USE_QASAN",
"AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", NULL
"AFL_NYX_HANDLE_INVALID_WRITE", "AFL_NYX_LOG", "AFL_NYX_REUSE_SNAPSHOT",
"AFL_PASSTHROUGH", "AFL_PATH", "AFL_PERFORMANCE_FILE",
"AFL_PERSISTENT_RECORD", "AFL_POST_PROCESS_KEEP_ORIGINAL", "AFL_PRELOAD",
"AFL_TARGET_ENV", "AFL_PYTHON_MODULE", "AFL_QEMU_CUSTOM_BIN",
"AFL_QEMU_COMPCOV", "AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_DEBUG_MAPS",
"AFL_QEMU_DISABLE_CACHE", "AFL_QEMU_DRIVER_NO_HOOK", "AFL_QEMU_FORCE_DFL",
"AFL_QEMU_PERSISTENT_ADDR", "AFL_QEMU_PERSISTENT_CNT",
"AFL_QEMU_PERSISTENT_GPR", "AFL_QEMU_PERSISTENT_HOOK",
"AFL_QEMU_PERSISTENT_MEM", "AFL_QEMU_PERSISTENT_RET",
"AFL_QEMU_PERSISTENT_RETADDR_OFFSET", "AFL_QEMU_PERSISTENT_EXITS",
"AFL_QEMU_INST_RANGES", "AFL_QEMU_EXCLUDE_RANGES", "AFL_QEMU_SNAPSHOT",
"AFL_QEMU_TRACK_UNSTABLE", "AFL_QUIET", "AFL_RANDOM_ALLOC_CANARY",
"AFL_REAL_PATH", "AFL_SHA1_FILENAMES", "AFL_SHUFFLE_QUEUE",
"AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ", "AFL_SKIP_CRASHES",
"AFL_SKIP_OSSFUZZ", "AFL_STATSD", "AFL_STATSD_HOST", "AFL_STATSD_PORT",
"AFL_STATSD_TAGS_FLAVOR", "AFL_SYNC_TIME", "AFL_TESTCACHE_SIZE",
"AFL_TESTCACHE_ENTRIES", "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE",
"AFL_TRACE_PC", "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC",
"AFL_USE_UBSAN", "AFL_USE_TSAN", "AFL_USE_CFISAN", "AFL_USE_LSAN",
"AFL_WINE_PATH", "AFL_NO_SNAPSHOT", "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN",
"AFL_USE_QASAN", "AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", NULL
};

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>>
@ -188,6 +188,8 @@ typedef struct afl_forkserver {
u8 persistent_mode;
u32 max_length;
#ifdef __linux__
nyx_plugin_handler_t *nyx_handlers;
char *out_dir_path; /* path to the output directory */

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>

738
include/t1ha.h Normal file
View File

@ -0,0 +1,738 @@
/*
* Copyright (c) 2016-2020 Positive Technologies, https://www.ptsecurity.com,
* Fast Positive Hash.
*
* Portions Copyright (c) 2010-2020 Leonid Yuriev <leo@yuriev.ru>,
* The 1Hippeus project (t1h).
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgement in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
/*
* t1ha = { Fast Positive Hash, aka "Позитивный Хэш" }
* by [Positive Technologies](https://www.ptsecurity.ru)
*
* Briefly, it is a 64-bit Hash Function:
* 1. Created for 64-bit little-endian platforms, in predominantly for x86_64,
* but portable and without penalties it can run on any 64-bit CPU.
* 2. In most cases up to 15% faster than City64, xxHash, mum-hash, metro-hash
* and all others portable hash-functions (which do not use specific
* hardware tricks).
* 3. Not suitable for cryptography.
*
* The Future will (be) Positive. Всё будет хорошо.
*
* ACKNOWLEDGEMENT:
* The t1ha was originally developed by Leonid Yuriev (Леонид Юрьев)
* for The 1Hippeus project - zerocopy messaging in the spirit of Sparta!
*/
#pragma once
/*****************************************************************************
*
* PLEASE PAY ATTENTION TO THE FOLLOWING NOTES
* about macros definitions which controls t1ha behaviour and/or performance.
*
*
* 1) T1HA_SYS_UNALIGNED_ACCESS = Defines the system/platform/CPU/architecture
* abilities for unaligned data access.
*
* By default, when the T1HA_SYS_UNALIGNED_ACCESS not defined,
* it will defined on the basis hardcoded knowledge about of capabilities
* of most common CPU architectures. But you could override this
* default behavior when build t1ha library itself:
*
* // To disable unaligned access at all.
* #define T1HA_SYS_UNALIGNED_ACCESS 0
*
* // To enable unaligned access, but indicate that it significantly slow.
* #define T1HA_SYS_UNALIGNED_ACCESS 1
*
* // To enable unaligned access, and indicate that it effecient.
* #define T1HA_SYS_UNALIGNED_ACCESS 2
*
*
* 2) T1HA_USE_FAST_ONESHOT_READ = Controls the data reads at the end of buffer.
*
* When defined to non-zero, t1ha will use 'one shot' method for reading
* up to 8 bytes at the end of data. In this case just the one 64-bit read
* will be performed even when the available less than 8 bytes.
*
* This is little bit faster that switching by length of data tail.
* Unfortunately this will triggering a false-positive alarms from Valgrind,
* AddressSanitizer and other similar tool.
*
* By default, t1ha defines it to 1, but you could override this
* default behavior when build t1ha library itself:
*
* // For little bit faster and small code.
* #define T1HA_USE_FAST_ONESHOT_READ 1
*
* // For calmness if doubt.
* #define T1HA_USE_FAST_ONESHOT_READ 0
*
*
* 3) T1HA0_RUNTIME_SELECT = Controls choice fastest function in runtime.
*
* t1ha library offers the t1ha0() function as the fastest for current CPU.
* But actual CPU's features/capabilities and may be significantly different,
* especially on x86 platform. Therefore, internally, t1ha0() may require
* dynamic dispatching for choice best implementation.
*
* By default, t1ha enables such runtime choice and (may be) corresponding
* indirect calls if it reasonable, but you could override this default
* behavior when build t1ha library itself:
*
* // To enable runtime choice of fastest implementation.
* #define T1HA0_RUNTIME_SELECT 1
*
* // To disable runtime choice of fastest implementation.
* #define T1HA0_RUNTIME_SELECT 0
*
* When T1HA0_RUNTIME_SELECT is nonzero the t1ha0_resolve() function could
* be used to get actual t1ha0() implementation address at runtime. This is
* useful for two cases:
* - calling by local pointer-to-function usually is little
* bit faster (less overhead) than via a PLT thru the DSO boundary.
* - GNU Indirect functions (see below) don't supported by environment
* and calling by t1ha0_funcptr is not available and/or expensive.
*
* 4) T1HA_USE_INDIRECT_FUNCTIONS = Controls usage of GNU Indirect functions.
*
* In continue of T1HA0_RUNTIME_SELECT the T1HA_USE_INDIRECT_FUNCTIONS
* controls usage of ELF indirect functions feature. In general, when
* available, this reduces overhead of indirect function's calls though
* a DSO-bundary (https://sourceware.org/glibc/wiki/GNU_IFUNC).
*
* By default, t1ha engage GNU Indirect functions when it available
* and useful, but you could override this default behavior when build
* t1ha library itself:
*
* // To enable use of GNU ELF Indirect functions.
* #define T1HA_USE_INDIRECT_FUNCTIONS 1
*
* // To disable use of GNU ELF Indirect functions. This may be useful
* // if the actual toolchain or the system's loader don't support ones.
* #define T1HA_USE_INDIRECT_FUNCTIONS 0
*
* 5) T1HA0_AESNI_AVAILABLE = Controls AES-NI detection and dispatching on x86.
*
* In continue of T1HA0_RUNTIME_SELECT the T1HA0_AESNI_AVAILABLE controls
* detection and usage of AES-NI CPU's feature. On the other hand, this
* requires compiling parts of t1ha library with certain properly options,
* and could be difficult or inconvenient in some cases.
*
* By default, t1ha engade AES-NI for t1ha0() on the x86 platform, but
* you could override this default behavior when build t1ha library itself:
*
* // To disable detection and usage of AES-NI instructions for t1ha0().
* // This may be useful when you unable to build t1ha library properly
* // or known that AES-NI will be unavailable at the deploy.
* #define T1HA0_AESNI_AVAILABLE 0
*
* // To force detection and usage of AES-NI instructions for t1ha0(),
* // but I don't known reasons to anybody would need this.
* #define T1HA0_AESNI_AVAILABLE 1
*
* 6) T1HA0_DISABLED, T1HA1_DISABLED, T1HA2_DISABLED = Controls availability of
* t1ha functions.
*
* In some cases could be useful to import/use only few of t1ha functions
* or just the one. So, this definitions allows disable corresponding parts
* of t1ha library.
*
* // To disable t1ha0(), t1ha0_32le(), t1ha0_32be() and all AES-NI.
* #define T1HA0_DISABLED
*
* // To disable t1ha1_le() and t1ha1_be().
* #define T1HA1_DISABLED
*
* // To disable t1ha2_atonce(), t1ha2_atonce128() and so on.
* #define T1HA2_DISABLED
*
*****************************************************************************/
#define T1HA_VERSION_MAJOR 2
#define T1HA_VERSION_MINOR 1
#define T1HA_VERSION_RELEASE 1
#ifndef __has_attribute
#define __has_attribute(x) (0)
#endif
#ifndef __has_include
#define __has_include(x) (0)
#endif
#ifndef __GNUC_PREREQ
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
#define __GNUC_PREREQ(maj, min) \
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
#else
#define __GNUC_PREREQ(maj, min) 0
#endif
#endif /* __GNUC_PREREQ */
#ifndef __CLANG_PREREQ
#ifdef __clang__
#define __CLANG_PREREQ(maj, min) \
((__clang_major__ << 16) + __clang_minor__ >= ((maj) << 16) + (min))
#else
#define __CLANG_PREREQ(maj, min) (0)
#endif
#endif /* __CLANG_PREREQ */
#ifndef __LCC_PREREQ
#ifdef __LCC__
#define __LCC_PREREQ(maj, min) \
((__LCC__ << 16) + __LCC_MINOR__ >= ((maj) << 16) + (min))
#else
#define __LCC_PREREQ(maj, min) (0)
#endif
#endif /* __LCC_PREREQ */
/*****************************************************************************/
#ifdef _MSC_VER
/* Avoid '16' bytes padding added after data member 't1ha_context::total'
* and other warnings from std-headers if warning-level > 3. */
#pragma warning(push, 3)
#endif
#if defined(__cplusplus) && __cplusplus >= 201103L
#include <climits>
#include <cstddef>
#include <cstdint>
#else
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
#endif
/*****************************************************************************/
#if defined(i386) || defined(__386) || defined(__i386) || defined(__i386__) || \
defined(i486) || defined(__i486) || defined(__i486__) || \
defined(i586) | defined(__i586) || defined(__i586__) || defined(i686) || \
defined(__i686) || defined(__i686__) || defined(_M_IX86) || \
defined(_X86_) || defined(__THW_INTEL__) || defined(__I86__) || \
defined(__INTEL__) || defined(__x86_64) || defined(__x86_64__) || \
defined(__amd64__) || defined(__amd64) || defined(_M_X64) || \
defined(_M_AMD64) || defined(__IA32__) || defined(__INTEL__)
#ifndef __ia32__
/* LY: define neutral __ia32__ for x86 and x86-64 archs */
#define __ia32__ 1
#endif /* __ia32__ */
#if !defined(__amd64__) && (defined(__x86_64) || defined(__x86_64__) || \
defined(__amd64) || defined(_M_X64))
/* LY: define trusty __amd64__ for all AMD64/x86-64 arch */
#define __amd64__ 1
#endif /* __amd64__ */
#endif /* all x86 */
#if !defined(__BYTE_ORDER__) || !defined(__ORDER_LITTLE_ENDIAN__) || \
!defined(__ORDER_BIG_ENDIAN__)
/* *INDENT-OFF* */
/* clang-format off */
#if defined(__GLIBC__) || defined(__GNU_LIBRARY__) || defined(__ANDROID__) || \
defined(HAVE_ENDIAN_H) || __has_include(<endian.h>)
#include <endian.h>
#elif defined(__APPLE__) || defined(__MACH__) || defined(__OpenBSD__) || \
defined(HAVE_MACHINE_ENDIAN_H) || __has_include(<machine/endian.h>)
#include <machine/endian.h>
#elif defined(HAVE_SYS_ISA_DEFS_H) || __has_include(<sys/isa_defs.h>)
#include <sys/isa_defs.h>
#elif (defined(HAVE_SYS_TYPES_H) && defined(HAVE_SYS_ENDIAN_H)) || \
(__has_include(<sys/types.h>) && __has_include(<sys/endian.h>))
#include <sys/endian.h>
#include <sys/types.h>
#elif defined(__bsdi__) || defined(__DragonFly__) || defined(__FreeBSD__) || \
defined(__NETBSD__) || defined(__NetBSD__) || \
defined(HAVE_SYS_PARAM_H) || __has_include(<sys/param.h>)
#include <sys/param.h>
#endif /* OS */
/* *INDENT-ON* */
/* clang-format on */
#if defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && defined(__BIG_ENDIAN)
#define __ORDER_LITTLE_ENDIAN__ __LITTLE_ENDIAN
#define __ORDER_BIG_ENDIAN__ __BIG_ENDIAN
#define __BYTE_ORDER__ __BYTE_ORDER
#elif defined(_BYTE_ORDER) && defined(_LITTLE_ENDIAN) && defined(_BIG_ENDIAN)
#define __ORDER_LITTLE_ENDIAN__ _LITTLE_ENDIAN
#define __ORDER_BIG_ENDIAN__ _BIG_ENDIAN
#define __BYTE_ORDER__ _BYTE_ORDER
#else
#define __ORDER_LITTLE_ENDIAN__ 1234
#define __ORDER_BIG_ENDIAN__ 4321
#if defined(__LITTLE_ENDIAN__) || \
(defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)) || \
defined(__ARMEL__) || defined(__THUMBEL__) || \
defined(__AARCH64EL__) || defined(__MIPSEL__) || defined(_MIPSEL) || \
defined(__MIPSEL) || defined(_M_ARM) || defined(_M_ARM64) || \
defined(__e2k__) || defined(__elbrus_4c__) || \
defined(__elbrus_8c__) || defined(__bfin__) || defined(__BFIN__) || \
defined(__ia64__) || defined(_IA64) || defined(__IA64__) || \
defined(__ia64) || defined(_M_IA64) || defined(__itanium__) || \
defined(__ia32__) || defined(__CYGWIN__) || defined(_WIN64) || \
defined(_WIN32) || defined(__TOS_WIN__) || defined(__WINDOWS__)
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
#elif defined(__BIG_ENDIAN__) || \
(defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)) || \
defined(__ARMEB__) || defined(__THUMBEB__) || \
defined(__AARCH64EB__) || defined(__MIPSEB__) || defined(_MIPSEB) || \
defined(__MIPSEB) || defined(__m68k__) || defined(M68000) || \
defined(__hppa__) || defined(__hppa) || defined(__HPPA__) || \
defined(__sparc__) || defined(__sparc) || defined(__370__) || \
defined(__THW_370__) || defined(__s390__) || defined(__s390x__) || \
defined(__SYSC_ZARCH__)
#define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__
#else
#error __BYTE_ORDER__ should be defined.
#endif /* Arch */
#endif
#endif /* __BYTE_ORDER__ || __ORDER_LITTLE_ENDIAN__ || __ORDER_BIG_ENDIAN__ */
/*****************************************************************************/
#ifndef __dll_export
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#if defined(__GNUC__) || __has_attribute(dllexport)
#define __dll_export __attribute__((dllexport))
#else
#define __dll_export __declspec(dllexport)
#endif
#elif defined(__GNUC__) || __has_attribute(__visibility__)
#define __dll_export __attribute__((__visibility__("default")))
#else
#define __dll_export
#endif
#endif /* __dll_export */
#ifndef __dll_import
#if defined(_WIN32) || defined(_WIN64) || defined(__CYGWIN__)
#if defined(__GNUC__) || __has_attribute(dllimport)
#define __dll_import __attribute__((dllimport))
#else
#define __dll_import __declspec(dllimport)
#endif
#elif defined(__GNUC__) || __has_attribute(__visibility__)
#define __dll_import __attribute__((__visibility__("default")))
#else
#define __dll_import
#endif
#endif /* __dll_import */
#ifndef __force_inline
#ifdef _MSC_VER
#define __force_inline __forceinline
#elif __GNUC_PREREQ(3, 2) || __has_attribute(__always_inline__)
#define __force_inline __inline __attribute__((__always_inline__))
#else
#define __force_inline __inline
#endif
#endif /* __force_inline */
#ifndef T1HA_API
#if defined(t1ha_EXPORTS)
#define T1HA_API __dll_export
#elif defined(t1ha_IMPORTS)
#define T1HA_API __dll_import
#else
#define T1HA_API
#endif
#endif /* T1HA_API */
#if defined(_MSC_VER) && defined(__ia32__)
#define T1HA_ALIGN_PREFIX __declspec(align(32)) /* required only for SIMD */
#else
#define T1HA_ALIGN_PREFIX
#endif /* _MSC_VER */
#if defined(__GNUC__) && defined(__ia32__)
#define T1HA_ALIGN_SUFFIX \
__attribute__((__aligned__(32))) /* required only for SIMD */
#else
#define T1HA_ALIGN_SUFFIX
#endif /* GCC x86 */
#ifndef T1HA_USE_INDIRECT_FUNCTIONS
/* GNU ELF indirect functions usage control. For more info please see
* https://en.wikipedia.org/wiki/Executable_and_Linkable_Format
* and https://sourceware.org/glibc/wiki/GNU_IFUNC */
#if defined(__ELF__) && defined(__amd64__) && \
(__has_attribute(__ifunc__) || \
(!defined(__clang__) && defined(__GNUC__) && __GNUC__ >= 4 && \
!defined(__SANITIZE_ADDRESS__) && !defined(__SSP_ALL__)))
/* Enable gnu_indirect_function by default if :
* - ELF AND x86_64
* - attribute(__ifunc__) is available OR
* GCC >= 4 WITHOUT -fsanitize=address NOR -fstack-protector-all */
#define T1HA_USE_INDIRECT_FUNCTIONS 1
#else
#define T1HA_USE_INDIRECT_FUNCTIONS 0
#endif
#endif /* T1HA_USE_INDIRECT_FUNCTIONS */
#if __GNUC_PREREQ(4, 0)
#pragma GCC visibility push(hidden)
#endif /* __GNUC_PREREQ(4,0) */
#ifdef __cplusplus
extern "C" {
#endif
typedef union T1HA_ALIGN_PREFIX t1ha_state256 {
uint8_t bytes[32];
uint32_t u32[8];
uint64_t u64[4];
struct {
uint64_t a, b, c, d;
} n;
} t1ha_state256_t T1HA_ALIGN_SUFFIX;
typedef struct t1ha_context {
t1ha_state256_t state;
t1ha_state256_t buffer;
size_t partial;
uint64_t total;
} t1ha_context_t;
#ifdef _MSC_VER
#pragma warning(pop)
#endif
/******************************************************************************
*
* Self-testing API.
*
* Unfortunately, some compilers (exactly only Microsoft Visual C/C++) has
* a bugs which leads t1ha-functions to produce wrong results. This API allows
* check the correctness of the actual code in runtime.
*
* All check-functions returns 0 on success, or -1 in case the corresponding
* hash-function failed verification. PLEASE, always perform such checking at
* initialization of your code, if you using MSVC or other troubleful compilers.
*/
T1HA_API int t1ha_selfcheck__all_enabled(void);
#ifndef T1HA2_DISABLED
T1HA_API int t1ha_selfcheck__t1ha2_atonce(void);
T1HA_API int t1ha_selfcheck__t1ha2_atonce128(void);
T1HA_API int t1ha_selfcheck__t1ha2_stream(void);
T1HA_API int t1ha_selfcheck__t1ha2(void);
#endif /* T1HA2_DISABLED */
#ifndef T1HA1_DISABLED
T1HA_API int t1ha_selfcheck__t1ha1_le(void);
T1HA_API int t1ha_selfcheck__t1ha1_be(void);
T1HA_API int t1ha_selfcheck__t1ha1(void);
#endif /* T1HA1_DISABLED */
#ifndef T1HA0_DISABLED
T1HA_API int t1ha_selfcheck__t1ha0_32le(void);
T1HA_API int t1ha_selfcheck__t1ha0_32be(void);
T1HA_API int t1ha_selfcheck__t1ha0(void);
/* Define T1HA0_AESNI_AVAILABLE to 0 for disable AES-NI support. */
#ifndef T1HA0_AESNI_AVAILABLE
#if defined(__e2k__) || \
(defined(__ia32__) && (!defined(_M_IX86) || _MSC_VER > 1800))
#define T1HA0_AESNI_AVAILABLE 1
#else
#define T1HA0_AESNI_AVAILABLE 0
#endif
#endif /* ifndef T1HA0_AESNI_AVAILABLE */
#if T1HA0_AESNI_AVAILABLE
T1HA_API int t1ha_selfcheck__t1ha0_ia32aes_noavx(void);
T1HA_API int t1ha_selfcheck__t1ha0_ia32aes_avx(void);
#ifndef __e2k__
T1HA_API int t1ha_selfcheck__t1ha0_ia32aes_avx2(void);
#endif
#endif /* if T1HA0_AESNI_AVAILABLE */
#endif /* T1HA0_DISABLED */
/******************************************************************************
*
* t1ha2 = 64 and 128-bit, SLIGHTLY MORE ATTENTION FOR QUALITY AND STRENGTH.
*
* - The recommended version of "Fast Positive Hash" with good quality
* for checksum, hash tables and fingerprinting.
* - Portable and extremely efficiency on modern 64-bit CPUs.
* Designed for 64-bit little-endian platforms,
* in other cases will runs slowly.
* - Great quality of hashing and still faster than other non-t1ha hashes.
* Provides streaming mode and 128-bit result.
*
* Note: Due performance reason 64- and 128-bit results are completely
* different each other, i.e. 64-bit result is NOT any part of 128-bit.
*/
#ifndef T1HA2_DISABLED
/* The at-once variant with 64-bit result */
T1HA_API uint64_t t1ha2_atonce(const void *data, size_t length, uint64_t seed);
/* The at-once variant with 128-bit result.
* Argument `extra_result` is NOT optional and MUST be valid.
* The high 64-bit part of 128-bit hash will be always unconditionally
* stored to the address given by `extra_result` argument. */
T1HA_API uint64_t t1ha2_atonce128(uint64_t *__restrict extra_result,
const void *__restrict data, size_t length,
uint64_t seed);
/* The init/update/final trinity for streaming.
* Return 64 or 128-bit result depentently from `extra_result` argument. */
T1HA_API void t1ha2_init(t1ha_context_t *ctx, uint64_t seed_x, uint64_t seed_y);
T1HA_API void t1ha2_update(t1ha_context_t *__restrict ctx,
const void *__restrict data, size_t length);
/* Argument `extra_result` is optional and MAY be NULL.
* - If `extra_result` is NOT NULL then the 128-bit hash will be calculated,
* and high 64-bit part of it will be stored to the address given
* by `extra_result` argument.
* - Otherwise the 64-bit hash will be calculated
* and returned from function directly.
*
* Note: Due performance reason 64- and 128-bit results are completely
* different each other, i.e. 64-bit result is NOT any part of 128-bit. */
T1HA_API uint64_t t1ha2_final(t1ha_context_t *__restrict ctx,
uint64_t *__restrict extra_result /* optional */);
#endif /* T1HA2_DISABLED */
/******************************************************************************
*
* t1ha1 = 64-bit, BASELINE FAST PORTABLE HASH:
*
* - Runs faster on 64-bit platforms in other cases may runs slowly.
* - Portable and stable, returns same 64-bit result
* on all architectures and CPUs.
* - Unfortunately it fails the "strict avalanche criteria",
* see test results at https://github.com/demerphq/smhasher.
*
* This flaw is insignificant for the t1ha1() purposes and imperceptible
* from a practical point of view.
* However, nowadays this issue has resolved in the next t1ha2(),
* that was initially planned to providing a bit more quality.
*/
#ifndef T1HA1_DISABLED
/* The little-endian variant. */
T1HA_API uint64_t t1ha1_le(const void *data, size_t length, uint64_t seed);
/* The big-endian variant. */
T1HA_API uint64_t t1ha1_be(const void *data, size_t length, uint64_t seed);
#endif /* T1HA1_DISABLED */
/******************************************************************************
*
* t1ha0 = 64-bit, JUST ONLY FASTER:
*
* - Provides fast-as-possible hashing for current CPU, including
* 32-bit systems and engaging the available hardware acceleration.
* - It is a facade that selects most quick-and-dirty hash
* for the current processor. For instance, on IA32 (x86) actual function
* will be selected in runtime, depending on current CPU capabilities
*
* BE CAREFUL!!! THIS IS MEANS:
*
* 1. The quality of hash is a subject for tradeoffs with performance.
* So, the quality and strength of t1ha0() may be lower than t1ha1(),
* especially on 32-bit targets, but then much faster.
* However, guaranteed that it passes all SMHasher tests.
*
* 2. No warranty that the hash result will be same for particular
* key on another machine or another version of libt1ha.
*
* Briefly, such hash-results and their derivatives, should be
* used only in runtime, but should not be persist or transferred
* over a network.
*
*
* When T1HA0_RUNTIME_SELECT is nonzero the t1ha0_resolve() function could
* be used to get actual t1ha0() implementation address at runtime. This is
* useful for two cases:
* - calling by local pointer-to-function usually is little
* bit faster (less overhead) than via a PLT thru the DSO boundary.
* - GNU Indirect functions (see below) don't supported by environment
* and calling by t1ha0_funcptr is not available and/or expensive.
*/
#ifndef T1HA0_DISABLED
/* The little-endian variant for 32-bit CPU. */
uint64_t t1ha0_32le(const void *data, size_t length, uint64_t seed);
/* The big-endian variant for 32-bit CPU. */
uint64_t t1ha0_32be(const void *data, size_t length, uint64_t seed);
/* Define T1HA0_AESNI_AVAILABLE to 0 for disable AES-NI support. */
#ifndef T1HA0_AESNI_AVAILABLE
#if defined(__e2k__) || \
(defined(__ia32__) && (!defined(_M_IX86) || _MSC_VER > 1800))
#define T1HA0_AESNI_AVAILABLE 1
#else
#define T1HA0_AESNI_AVAILABLE 0
#endif
#endif /* T1HA0_AESNI_AVAILABLE */
/* Define T1HA0_RUNTIME_SELECT to 0 for disable dispatching t1ha0 at runtime.
*/
#ifndef T1HA0_RUNTIME_SELECT
#if T1HA0_AESNI_AVAILABLE && !defined(__e2k__)
#define T1HA0_RUNTIME_SELECT 1
#else
#define T1HA0_RUNTIME_SELECT 0
#endif
#endif /* T1HA0_RUNTIME_SELECT */
#if !T1HA0_RUNTIME_SELECT && !defined(T1HA0_USE_DEFINE)
#if defined(__LCC__)
#define T1HA0_USE_DEFINE 1
#else
#define T1HA0_USE_DEFINE 0
#endif
#endif /* T1HA0_USE_DEFINE */
#if T1HA0_AESNI_AVAILABLE
uint64_t t1ha0_ia32aes_noavx(const void *data, size_t length, uint64_t seed);
uint64_t t1ha0_ia32aes_avx(const void *data, size_t length, uint64_t seed);
#ifndef __e2k__
uint64_t t1ha0_ia32aes_avx2(const void *data, size_t length, uint64_t seed);
#endif
#endif /* T1HA0_AESNI_AVAILABLE */
#if T1HA0_RUNTIME_SELECT
typedef uint64_t (*t1ha0_function_t)(const void *, size_t, uint64_t);
T1HA_API t1ha0_function_t t1ha0_resolve(void);
#if T1HA_USE_INDIRECT_FUNCTIONS
T1HA_API uint64_t t1ha0(const void *data, size_t length, uint64_t seed);
#else
/* Otherwise function pointer will be used.
* Unfortunately this may cause some overhead calling. */
T1HA_API extern uint64_t (*t1ha0_funcptr)(const void *data, size_t length,
uint64_t seed);
static __force_inline uint64_t t1ha0(const void *data, size_t length,
uint64_t seed) {
return t1ha0_funcptr(data, length, seed);
}
#endif /* T1HA_USE_INDIRECT_FUNCTIONS */
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#if T1HA0_USE_DEFINE
#if (UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul) && \
(!defined(T1HA1_DISABLED) || !defined(T1HA2_DISABLED))
#if defined(T1HA1_DISABLED)
#define t1ha0 t1ha2_atonce
#else
#define t1ha0 t1ha1_be
#endif /* T1HA1_DISABLED */
#else /* 32/64 */
#define t1ha0 t1ha0_32be
#endif /* 32/64 */
#else /* T1HA0_USE_DEFINE */
static __force_inline uint64_t t1ha0(const void *data, size_t length,
uint64_t seed) {
#if (UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul) && \
(!defined(T1HA1_DISABLED) || !defined(T1HA2_DISABLED))
#if defined(T1HA1_DISABLED)
return t1ha2_atonce(data, length, seed);
#else
return t1ha1_be(data, length, seed);
#endif /* T1HA1_DISABLED */
#else /* 32/64 */
return t1ha0_32be(data, length, seed);
#endif /* 32/64 */
}
#endif /* !T1HA0_USE_DEFINE */
#else /* !T1HA0_RUNTIME_SELECT && __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__ */
#if T1HA0_USE_DEFINE
#if (UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul) && \
(!defined(T1HA1_DISABLED) || !defined(T1HA2_DISABLED))
#if defined(T1HA1_DISABLED)
#define t1ha0 t1ha2_atonce
#else
#define t1ha0 t1ha1_le
#endif /* T1HA1_DISABLED */
#else /* 32/64 */
#define t1ha0 t1ha0_32le
#endif /* 32/64 */
#else
static __force_inline uint64_t t1ha0(const void *data, size_t length,
uint64_t seed) {
#if (UINTPTR_MAX > 0xffffFFFFul || ULONG_MAX > 0xffffFFFFul) && \
(!defined(T1HA1_DISABLED) || !defined(T1HA2_DISABLED))
#if defined(T1HA1_DISABLED)
return t1ha2_atonce(data, length, seed);
#else
return t1ha1_le(data, length, seed);
#endif /* T1HA1_DISABLED */
#else /* 32/64 */
return t1ha0_32le(data, length, seed);
#endif /* 32/64 */
}
#endif /* !T1HA0_USE_DEFINE */
#endif /* !T1HA0_RUNTIME_SELECT */
#endif /* T1HA0_DISABLED */
#ifdef __cplusplus
}
#endif
#if __GNUC_PREREQ(4, 0)
#pragma GCC visibility pop
#endif /* __GNUC_PREREQ(4,0) */

183
include/t1ha0_ia32aes_b.h Normal file
View File

@ -0,0 +1,183 @@
/*
* Copyright (c) 2016-2020 Positive Technologies, https://www.ptsecurity.com,
* Fast Positive Hash.
*
* Portions Copyright (c) 2010-2020 Leonid Yuriev <leo@yuriev.ru>,
* The 1Hippeus project (t1h).
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgement in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
/*
* t1ha = { Fast Positive Hash, aka "Позитивный Хэш" }
* by [Positive Technologies](https://www.ptsecurity.ru)
*
* Briefly, it is a 64-bit Hash Function:
* 1. Created for 64-bit little-endian platforms, in predominantly for x86_64,
* but portable and without penalties it can run on any 64-bit CPU.
* 2. In most cases up to 15% faster than City64, xxHash, mum-hash, metro-hash
* and all others portable hash-functions (which do not use specific
* hardware tricks).
* 3. Not suitable for cryptography.
*
* The Future will (be) Positive. Всё будет хорошо.
*
* ACKNOWLEDGEMENT:
* The t1ha was originally developed by Leonid Yuriev (Леонид Юрьев)
* for The 1Hippeus project - zerocopy messaging in the spirit of Sparta!
*/
#include "t1ha_bits.h"
#include "t1ha_selfcheck.h"
#if T1HA0_AESNI_AVAILABLE
uint64_t T1HA_IA32AES_NAME(const void *data, uint32_t len) {
uint64_t a = 0;
uint64_t b = len;
if (likely(len > 32)) {
__m128i x = _mm_set_epi64x(a, b);
__m128i y = _mm_aesenc_si128(x, _mm_set_epi64x(prime_0, prime_1));
const __m128i *v = (const __m128i *)data;
const __m128i *const detent =
(const __m128i *)((const uint8_t *)data + (len & ~15ul));
data = detent;
if (len & 16) {
x = _mm_add_epi64(x, _mm_loadu_si128(v++));
y = _mm_aesenc_si128(x, y);
}
len &= 15;
if (v + 7 < detent) {
__m128i salt = y;
do {
__m128i t = _mm_aesenc_si128(_mm_loadu_si128(v++), salt);
t = _mm_aesdec_si128(t, _mm_loadu_si128(v++));
t = _mm_aesdec_si128(t, _mm_loadu_si128(v++));
t = _mm_aesdec_si128(t, _mm_loadu_si128(v++));
t = _mm_aesdec_si128(t, _mm_loadu_si128(v++));
t = _mm_aesdec_si128(t, _mm_loadu_si128(v++));
t = _mm_aesdec_si128(t, _mm_loadu_si128(v++));
t = _mm_aesdec_si128(t, _mm_loadu_si128(v++));
salt = _mm_add_epi64(salt, _mm_set_epi64x(prime_5, prime_6));
t = _mm_aesenc_si128(x, t);
x = _mm_add_epi64(y, x);
y = t;
} while (v + 7 < detent);
}
while (v < detent) {
__m128i v0y = _mm_add_epi64(y, _mm_loadu_si128(v++));
__m128i v1x = _mm_sub_epi64(x, _mm_loadu_si128(v++));
x = _mm_aesdec_si128(x, v0y);
y = _mm_aesdec_si128(y, v1x);
}
x = _mm_add_epi64(_mm_aesdec_si128(x, _mm_aesenc_si128(y, x)), y);
#if defined(__x86_64__) || defined(_M_X64)
#if defined(__SSE4_1__) || defined(__AVX__)
a = _mm_extract_epi64(x, 0);
b = _mm_extract_epi64(x, 1);
#else
a = _mm_cvtsi128_si64(x);
b = _mm_cvtsi128_si64(_mm_unpackhi_epi64(x, x));
#endif
#else
#if defined(__SSE4_1__) || defined(__AVX__)
a = (uint32_t)_mm_extract_epi32(x, 0) | (uint64_t)_mm_extract_epi32(x, 1)
<< 32;
b = (uint32_t)_mm_extract_epi32(x, 2) | (uint64_t)_mm_extract_epi32(x, 3)
<< 32;
#else
a = (uint32_t)_mm_cvtsi128_si32(x);
a |= (uint64_t)_mm_cvtsi128_si32(_mm_shuffle_epi32(x, 1)) << 32;
x = _mm_unpackhi_epi64(x, x);
b = (uint32_t)_mm_cvtsi128_si32(x);
b |= (uint64_t)_mm_cvtsi128_si32(_mm_shuffle_epi32(x, 1)) << 32;
#endif
#endif
#ifdef __AVX__
_mm256_zeroupper();
#elif !(defined(_X86_64_) || defined(__x86_64__) || defined(_M_X64) || \
defined(__e2k__))
_mm_empty();
#endif
}
const uint64_t *v = (const uint64_t *)data;
switch (len) {
default:
mixup64(&a, &b, fetch64_le_unaligned(v++), prime_4);
/* fall through */
case 24:
case 23:
case 22:
case 21:
case 20:
case 19:
case 18:
case 17:
mixup64(&b, &a, fetch64_le_unaligned(v++), prime_3);
/* fall through */
case 16:
case 15:
case 14:
case 13:
case 12:
case 11:
case 10:
case 9:
mixup64(&a, &b, fetch64_le_unaligned(v++), prime_2);
/* fall through */
case 8:
case 7:
case 6:
case 5:
case 4:
case 3:
case 2:
case 1:
mixup64(&b, &a, tail64_le_unaligned(v, len), prime_1);
/* fall through */
case 0:
return final64(a, b);
}
}
#endif /* T1HA0_AESNI_AVAILABLE */
#undef T1HA_IA32AES_NAME

1423
include/t1ha_bits.h Normal file

File diff suppressed because it is too large Load Diff

77
include/t1ha_selfcheck.h Normal file
View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2016-2020 Positive Technologies, https://www.ptsecurity.com,
* Fast Positive Hash.
*
* Portions Copyright (c) 2010-2020 Leonid Yuriev <leo@yuriev.ru>,
* The 1Hippeus project (t1h).
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgement in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
/*
* t1ha = { Fast Positive Hash, aka "Позитивный Хэш" }
* by [Positive Technologies](https://www.ptsecurity.ru)
*
* Briefly, it is a 64-bit Hash Function:
* 1. Created for 64-bit little-endian platforms, in predominantly for x86_64,
* but portable and without penalties it can run on any 64-bit CPU.
* 2. In most cases up to 15% faster than City64, xxHash, mum-hash, metro-hash
* and all others portable hash-functions (which do not use specific
* hardware tricks).
* 3. Not suitable for cryptography.
*
* The Future will (be) Positive. Всё будет хорошо.
*
* ACKNOWLEDGEMENT:
* The t1ha was originally developed by Leonid Yuriev (Леонид Юрьев)
* for The 1Hippeus project - zerocopy messaging in the spirit of Sparta!
*/
#pragma once
#if defined(_MSC_VER) && _MSC_VER > 1800
#pragma warning(disable : 4464) /* relative include path contains '..' */
#endif /* MSVC */
#include "t1ha.h"
/***************************************************************************/
/* Self-checking */
extern const uint8_t t1ha_test_pattern[64];
int t1ha_selfcheck(uint64_t (*hash)(const void *, size_t, uint64_t),
const uint64_t *reference_values);
#ifndef T1HA2_DISABLED
extern const uint64_t t1ha_refval_2atonce[81];
extern const uint64_t t1ha_refval_2atonce128[81];
extern const uint64_t t1ha_refval_2stream[81];
extern const uint64_t t1ha_refval_2stream128[81];
#endif /* T1HA2_DISABLED */
#ifndef T1HA1_DISABLED
extern const uint64_t t1ha_refval_64le[81];
extern const uint64_t t1ha_refval_64be[81];
#endif /* T1HA1_DISABLED */
#ifndef T1HA0_DISABLED
extern const uint64_t t1ha_refval_32le[81];
extern const uint64_t t1ha_refval_32be[81];
#if T1HA0_AESNI_AVAILABLE
extern const uint64_t t1ha_refval_ia32aes_a[81];
extern const uint64_t t1ha_refval_ia32aes_b[81];
#endif /* T1HA0_AESNI_AVAILABLE */
#endif /* T1HA0_DISABLED */

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
Andrea Fioraldi <andreafioraldi@gmail.com>,
Dominik Maier <mail@dmnk.co>
@ -49,6 +49,14 @@ typedef uint128_t u128;
#define FS_ERROR_OLD_CMPLOG 32
#define FS_ERROR_OLD_CMPLOG_QEMU 64
/* New Forkserver */
#define FS_NEW_VERSION_MIN 1
#define FS_NEW_VERSION_MAX 1
#define FS_NEW_ERROR 0xeffe0000
#define FS_NEW_OPT_MAPSIZE 0x00000001 // parameter: 32 bit value
#define FS_NEW_OPT_SHDMEM_FUZZ 0x00000002 // parameter: none
#define FS_NEW_OPT_AUTODICT 0x00000800 // autodictionary data
/* Reporting options */
#define FS_OPT_ENABLED 0x80000001
#define FS_OPT_MAPSIZE 0x40000000

File diff suppressed because it is too large Load Diff

View File

@ -196,3 +196,33 @@ Then as first line after the `__AFL_LOOP` while loop:
```
And that is all!
## 6) Persistent record, and replay
If your software under test requires keeping a state between persistent loop iterations (i.e., a stateful network stack), you can use the `AFL_PERSISTENT_RECORD` variable as described in the [environment variables documentation](../docs/env_variables.md).
When `AFL_PERSISTENT_RECORD` is enabled, replay functionality is also included in the compiler-rt library. To replay a specific record, assign the record number to the AFL_PERSISTENT_REPLAY environment variable (i.e., `RECORD:XXXXX`` -> `AFL_PERSISTENT_REPLAY=XXXXX`), and run the test binary as you would normally do.
The directory where the record files live can be specified via the `AFL_PERSISTENT_DIR` environment varilable, otherwise by default it will be considered the current directory (`./`).
If your harness reads the input files from arguments using the special `@@` argument you will need to include support by enabling `AFL_PERSISTENT_ARGPARSE` in `config.h`.
In order to offer transparent support to harnesses using the `@@` command line argument, arguments are parsed by the `__afl_record_replay_init` init function. Since not all systems support passing arguments to initializers, this functionality is disabled by default, it's recommendable to use the `__AFL_FUZZ_TESTCASE_BUF/__AFL_FUZZ_TESTCASE_LEN` shared memory mechanism instead.
## 7) Drop-in persistent loop replay replacement
To use the replay functionality without having to use `afl-cc`, include the [include/record_compat.h](../include/afl-record_compat.h) header file. Together with the [include/afl-persistent-replay.h](../include/afl-persistent-replay.h) header included in it, `afl-record-compat.h` provides a drop-in replacement for the persistent loop mechanism.
```c
#ifndef __AFL_FUZZ_TESTCASE_LEN
// #define AFL_PERSISTENT_REPLAY_ARGPARSE
#include "afl-record-compat.h"
#endif
__AFL_FUZZ_INIT();
```
A simple example is provided in [persistent_demo_replay.c](../utils/replay_record/persistent_demo_replay.c).
Be aware that the [afl-record-compat.h](../include/afl-record-compat.h) header should only be included in a single compilation unit, or you will end up with clobbered functions and variables.
If you need a cleaner solution, you'll have to move the functions and variables defined in [include/record_compat.h](../include/afl-record-compat.h) and [include/afl-persistent-replay.h](../include/afl-persistent-replay.h) in a C file, and add the relevant declarations to a header file. After including the new header file, the compilation unit resulting from compiling the C file can then be linked with your program.

View File

@ -194,10 +194,13 @@ class ModuleSanitizerCoverageLTO
private:
void instrumentFunction(Function &F, DomTreeCallback DTCallback,
PostDomTreeCallback PDTCallback);
void InjectCoverageForIndirectCalls(Function &F,
ArrayRef<Instruction *> IndirCalls);
/* void InjectCoverageForIndirectCalls(Function &F,
ArrayRef<Instruction *>
IndirCalls);*/
bool InjectCoverage(Function &F, ArrayRef<BasicBlock *> AllBlocks,
bool IsLeafFunc = true);
bool Fake_InjectCoverage(Function &F, ArrayRef<BasicBlock *> AllBlocks,
bool IsLeafFunc = true);
GlobalVariable *CreateFunctionLocalArrayInSection(size_t NumElements,
Function &F, Type *Ty,
const char *Section);
@ -247,6 +250,9 @@ class ModuleSanitizerCoverageLTO
uint32_t afl_global_id = 0;
uint32_t unhandled = 0;
uint32_t select_cnt = 0;
uint32_t instrument_ctx = 0;
uint32_t instrument_ctx_max_depth = 0;
uint32_t extra_ctx_inst = 0;
uint64_t map_addr = 0;
const char *skip_nozero = NULL;
const char *use_threadsafe_counters = nullptr;
@ -257,11 +263,14 @@ class ModuleSanitizerCoverageLTO
IntegerType *Int32Tyi = NULL;
IntegerType *Int64Tyi = NULL;
ConstantInt *Zero = NULL;
ConstantInt *Zero32 = NULL;
ConstantInt *One = NULL;
LLVMContext *Ct = NULL;
Module *Mo = NULL;
GlobalVariable *AFLContext = NULL;
GlobalVariable *AFLMapPtr = NULL;
Value *MapPtrFixed = NULL;
AllocaInst *CTX_add = NULL;
std::ofstream dFile;
size_t found = 0;
// AFL++ END
@ -420,16 +429,51 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
setvbuf(stdout, NULL, _IONBF, 0);
if (getenv("AFL_DEBUG")) { debug = 1; }
if (getenv("AFL_LLVM_DICT2FILE_NO_MAIN")) { autodictionary_no_main = 1; }
if (getenv("AFL_LLVM_CALLER") || getenv("AFL_LLVM_CTX") ||
getenv("AFL_LLVM_LTO_CALLER") || getenv("AFL_LLVM_LTO_CTX")) {
instrument_ctx = 1;
}
if (getenv("AFL_LLVM_LTO_CALLER_DEPTH")) {
instrument_ctx_max_depth = atoi(getenv("AFL_LLVM_LTO_CALLER_DEPTH"));
} else if (getenv("AFL_LLVM_LTO_CTX_DEPTH")) {
instrument_ctx_max_depth = atoi(getenv("AFL_LLVM_LTO_CTX_DEPTH"));
} else if (getenv("AFL_LLVM_CALLER_DEPTH")) {
instrument_ctx_max_depth = atoi(getenv("AFL_LLVM_CALLER_DEPTH"));
} else if (getenv("AFL_LLVM_CTX_DEPTH")) {
instrument_ctx_max_depth = atoi(getenv("AFL_LLVM_CTX_DEPTH"));
}
if ((isatty(2) && !getenv("AFL_QUIET")) || debug) {
SAYF(cCYA "afl-llvm-lto" VERSION cRST
" by Marc \"vanHauser\" Heuse <mh@mh-sec.de>\n");
char buf[64] = {};
if (instrument_ctx) {
} else
snprintf(buf, sizeof(buf), " (CTX mode, depth %u)\n",
instrument_ctx_max_depth);
}
SAYF(cCYA "afl-llvm-lto" VERSION cRST
"%s by Marc \"vanHauser\" Heuse <mh@mh-sec.de>\n",
buf);
} else {
be_quiet = 1;
}
skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
use_threadsafe_counters = getenv("AFL_LLVM_THREADSAFE_INST");
@ -442,7 +486,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) {
dFile.open(ptr, std::ofstream::out | std::ofstream::app);
if (dFile.is_open()) WARNF("Cannot access document file %s", ptr);
if (!dFile.is_open()) WARNF("Cannot access document file %s", ptr);
}
@ -500,7 +544,12 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
}
AFLContext = new GlobalVariable(
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_ctx", 0,
GlobalVariable::GeneralDynamicTLSModel, 0, false);
Zero = ConstantInt::get(Int8Tyi, 0);
Zero32 = ConstantInt::get(Int32Tyi, 0);
One = ConstantInt::get(Int8Tyi, 1);
initInstrumentList();
@ -597,12 +646,12 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
}
dictionary.push_back(std::string((char *)&val, len));
found++;
++found;
if (val2) {
dictionary.push_back(std::string((char *)&val2, len));
found++;
++found;
}
@ -750,12 +799,12 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
else
Str2 = TmpStr.str();
if (debug)
/*if (debug)
fprintf(stderr, "F:%s %p(%s)->\"%s\"(%s) %p(%s)->\"%s\"(%s)\n",
FuncName.c_str(), Str1P, Str1P->getName().str().c_str(),
Str1.c_str(), HasStr1 == true ? "true" : "false", Str2P,
Str2P->getName().str().c_str(), Str2.c_str(),
HasStr2 == true ? "true" : "false");
HasStr2 == true ? "true" : "false");*/
// we handle the 2nd parameter first because of llvm memcpy
if (!HasStr2) {
@ -929,7 +978,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
'\0') {
thestring.append("\0", 1); // add null byte
optLen++;
++optLen;
}
@ -1080,7 +1129,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
for (auto token : dictionary) {
memlen += token.length();
count++;
++count;
}
@ -1101,7 +1150,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
ptrhld.get()[offset++] = (uint8_t)token.length();
memcpy(ptrhld.get() + offset, token.c_str(), token.length());
offset += token.length();
count++;
++count;
}
@ -1148,7 +1197,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
WARNF("No instrumentation targets found.");
else {
char modeline[100];
char modeline[128];
snprintf(modeline, sizeof(modeline), "%s%s%s%s%s%s",
getenv("AFL_HARDEN") ? "hardened" : "non-hardened",
getenv("AFL_USE_ASAN") ? ", ASAN" : "",
@ -1156,9 +1205,16 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
getenv("AFL_USE_TSAN") ? ", TSAN" : "",
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
OKF("Instrumented %u locations (%u selects) without collisions (%llu "
"collisions have been avoided) (%s mode).",
inst, select_cnt, calculateCollisions(inst), modeline);
char buf[64] = {};
if (instrument_ctx) {
snprintf(buf, sizeof(buf), " with %u extra map entries for CTX",
extra_ctx_inst);
}
OKF("Instrumented %u locations (%u selects)%s (%s mode).", inst,
select_cnt, buf, modeline);
}
@ -1239,6 +1295,57 @@ static bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB,
}
/// return the number of calls to this function
u32 countCallers(Function *F) {
u32 callers = 0;
if (!F) { return 0; }
for (auto *U : F->users()) {
if (auto *CI = dyn_cast<CallInst>(U)) {
++callers;
(void)(CI);
}
}
return callers;
}
/// return the calling function of a function - only if there is a single caller
Function *returnOnlyCaller(Function *F) {
Function *caller = NULL;
if (!F) { return NULL; }
for (auto *U : F->users()) {
if (auto *CI = dyn_cast<CallInst>(U)) {
if (caller == NULL) {
caller = CI->getParent()->getParent();
} else {
return NULL;
}
}
}
return caller;
}
void ModuleSanitizerCoverageLTO::instrumentFunction(
Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
@ -1272,6 +1379,37 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
// AFL++ START
if (!F.size()) return;
LLVMContext &Context = F.getContext();
MDNode *N = MDNode::get(Context, MDString::get(Context, "nosanitize"));
if (instrument_ctx) {
// we have to set __afl_ctx 0 for all indirect calls in all functions, even
// those not to be instrumented.
for (auto &BB : F) {
for (auto &IN : BB) {
if (auto *Call = dyn_cast<CallInst>(&IN)) {
if (Call->isIndirectCall()) {
IRBuilder<> Builder(IN.getContext());
Builder.SetInsertPoint(IN.getParent(), IN.getIterator());
StoreInst *StoreCtx = Builder.CreateStore(Zero32, AFLContext);
StoreCtx->setMetadata("nosanitize", N);
}
}
}
}
}
if (!isInInstrumentList(&F, FMNAME)) return;
// AFL++ END
@ -1285,13 +1423,299 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
const PostDominatorTree *PDT = PDTCallback(F);
bool IsLeafFunc = true;
uint32_t skip_next = 0;
uint32_t call_counter = 0, call_depth = 0;
uint32_t inst_save = inst, save_global = afl_global_id;
uint32_t inst_in_this_func = 0;
Function *caller = NULL;
LoadInst *PrevCtxLoad = NULL;
CTX_add = NULL;
if (debug) fprintf(stderr, "Function: %s\n", F.getName().str().c_str());
if (instrument_ctx) {
caller = &F;
call_counter = countCallers(caller);
Function *callee = caller;
if (call_counter == 1 && instrument_ctx_max_depth) {
++call_depth;
while (instrument_ctx_max_depth >= call_depth &&
((caller = returnOnlyCaller(callee)) || 1 == 1) &&
(call_counter = countCallers(callee)) == 1) {
if (debug && caller && callee)
fprintf(stderr, "DEBUG: another depth: %s <- %s [%u]\n",
callee->getName().str().c_str(),
caller->getName().str().c_str(), call_depth);
++call_depth;
callee = caller;
}
if (!caller && callee) {
caller = callee;
if (debug)
fprintf(stderr, "DEBUG: depth found: %s <- %s [count=%u, depth=%u]\n",
caller->getName().str().c_str(), F.getName().str().c_str(),
call_counter, call_depth);
}
}
if (debug && call_counter < 2) {
fprintf(stderr, "Function %s only %u (%s)\n", F.getName().str().c_str(),
call_counter, caller->getName().str().c_str());
}
if (call_counter == 1) {
call_counter = 0;
caller = NULL;
}
if (debug) {
fprintf(stderr, "DEBUG: result: Function=%s callers=%u depth=%u\n",
F.getName().str().c_str(), call_counter, call_depth);
}
if (call_counter > 1) {
// Fake instrumentation so we can count how many instrumentations there
// will be in this function
for (auto &BB : F) {
for (auto &IN : BB) {
CallInst *callInst = nullptr;
if ((callInst = dyn_cast<CallInst>(&IN))) {
Function *Callee = callInst->getCalledFunction();
if (!Callee) continue;
if (callInst->getCallingConv() != llvm::CallingConv::C) continue;
StringRef FuncName = Callee->getName();
if (FuncName.compare(StringRef("__afl_coverage_interesting")))
continue;
++inst;
}
SelectInst *selectInst = nullptr;
if ((selectInst = dyn_cast<SelectInst>(&IN))) {
Value *condition = selectInst->getCondition();
auto t = condition->getType();
if (t->getTypeID() == llvm::Type::IntegerTyID) {
inst += 2;
} else
#if LLVM_VERSION_MAJOR >= 14
if (t->getTypeID() == llvm::Type::FixedVectorTyID) {
FixedVectorType *tt = dyn_cast<FixedVectorType>(t);
if (tt) {
uint32_t elements = tt->getElementCount().getFixedValue();
inst += elements * 2;
}
} else
#endif
{
continue;
}
}
}
if (shouldInstrumentBlock(F, &BB, DT, PDT, Options))
BlocksToInstrument.push_back(&BB);
}
Fake_InjectCoverage(F, BlocksToInstrument, IsLeafFunc);
if (debug)
fprintf(stderr, "DEBUG: CTX: %u instrumentations\n", inst - inst_save);
// we only instrument functions that have more than one instrumented block
if (inst > inst_save + 1) {
inst_in_this_func = inst - inst_save;
bool done = false;
// in rare occasions there can be multiple entry points per function
for (auto &BB : F) {
if (&BB == &F.getEntryBlock() && done == false) {
// we insert a CTX value in all our callers:
IRBuilder<> Builder(Context);
CallInst *CI = NULL;
Function *F2 = NULL;
uint32_t instrumented_calls = 0;
for (auto *U : caller->users()) {
if ((CI = dyn_cast<CallInst>(U))) {
F2 = CI->getParent()->getParent();
if (debug)
fprintf(stderr,
"DEBUG: CTX call insert %s [%u/%u] -> %s/%s\n",
F2->getName().str().c_str(), instrumented_calls + 1,
call_counter, caller->getName().str().c_str(),
F.getName().str().c_str());
Builder.SetInsertPoint(CI);
StoreInst *StoreCtx = Builder.CreateStore(
ConstantInt::get(Type::getInt32Ty(Context),
instrumented_calls++),
AFLContext);
StoreCtx->setMetadata("nosanitize", N);
}
}
if (instrumented_calls != call_counter) {
fprintf(stderr, "BUG! %s/%s <=> %u vs %u\n",
caller->getName().str().c_str(),
F.getName().str().c_str(), instrumented_calls,
call_counter);
exit(-1);
}
done = true;
}
// in all entrypoints we have to load the CTX value
if (&BB == &F.getEntryBlock()) {
Value *CTX_offset;
BasicBlock::iterator IP = BB.getFirstInsertionPt();
IRBuilder<> IRB(&(*IP));
PrevCtxLoad = IRB.CreateLoad(
#if LLVM_VERSION_MAJOR >= 14
IRB.getInt32Ty(),
#endif
AFLContext);
PrevCtxLoad->setMetadata("nosanitize", N);
CTX_offset = IRB.CreateMul(
ConstantInt::get(Type::getInt32Ty(Context), inst_in_this_func),
PrevCtxLoad, "CTXmul", false, true);
CTX_add =
IRB.CreateAlloca(Type::getInt32Ty(Context), nullptr, "CTX_add");
auto nosan = IRB.CreateStore(CTX_offset, CTX_add);
nosan->setMetadata("nosanitize", N);
if (debug)
fprintf(
stderr, "DEBUG: extra CTX instrumentations for %s: %u * %u\n",
F.getName().str().c_str(), inst - inst_save, call_counter);
}
for (auto &IN : BB) {
// check all calls and where callee count == 1 instrument
// our current caller_id to __afl_ctx
if (auto callInst = dyn_cast<CallInst>(&IN)) {
Function *Callee = callInst->getCalledFunction();
if (countCallers(Callee) == 1) {
if (debug)
fprintf(stderr, "DEBUG: %s call to %s with only one caller\n",
F.getName().str().c_str(),
Callee->getName().str().c_str());
IRBuilder<> Builder(IN.getContext());
Builder.SetInsertPoint(callInst);
StoreInst *StoreCtx =
Builder.CreateStore(PrevCtxLoad, AFLContext);
StoreCtx->setMetadata("nosanitize", N);
}
}
}
}
}
}
inst = inst_save;
/* if (debug)
fprintf(stderr, "Next instrumentation (%u-%u=%u %u-%u=%u)\n", inst,
inst_save, inst - inst_save, afl_global_id, save_global,
afl_global_id - save_global);*/
}
for (auto &BB : F) {
skip_next = 0;
/*
uint32_t j = 0;
fprintf(stderr, "BB %p ============================================\n",
CTX_add);*/
for (auto &IN : BB) {
/* j++;
uint32_t i = 1;
std::string errMsg;
raw_string_ostream os(errMsg);
IN.print(os);
fprintf(stderr, "Next instruction, BB size now %zu: %02u %s\n",
BB.size(), j, os.str().c_str()); for (auto &IN2 : BB) {
std::string errMsg2;
raw_string_ostream os2(errMsg2);
IN2.print(os2);
fprintf(
stderr, "%s %02u: %s\n",
strcmp(os.str().c_str(), os2.str().c_str()) == 0 ? ">>>" : "
", i++, os2.str().c_str());
}*/
CallInst *callInst = nullptr;
if ((callInst = dyn_cast<CallInst>(&IN))) {
Function *Callee = callInst->getCalledFunction();
@ -1313,6 +1737,19 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue;
Value *val = ConstantInt::get(Int32Ty, ++afl_global_id);
if (CTX_add) {
IRBuilder<> Builder(Context);
LoadInst *CTX_load = Builder.CreateLoad(
#if LLVM_VERSION_MAJOR >= 14
Builder.getInt32Ty(),
#endif
CTX_add);
ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(CTX_load);
val = Builder.CreateAdd(val, CTX_load);
}
callInst->setOperand(1, val);
++inst;
@ -1320,13 +1757,11 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
SelectInst *selectInst = nullptr;
/*
std::string errMsg;
raw_string_ostream os(errMsg);
IN.print(os);
fprintf(stderr, "X(%u): %s\n", skip_next, os.str().c_str());
*/
if (!skip_next && (selectInst = dyn_cast<SelectInst>(&IN))) {
if ((selectInst = dyn_cast<SelectInst>(&IN))) {
if (!skip_next) {
// fprintf(stderr, "Select in\n");
uint32_t vector_cnt = 0;
Value *condition = selectInst->getCondition();
@ -1340,6 +1775,18 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
Value *val1 = ConstantInt::get(Int32Ty, ++afl_global_id);
Value *val2 = ConstantInt::get(Int32Ty, ++afl_global_id);
if (CTX_add) {
LoadInst *CTX_load = IRB.CreateLoad(
#if LLVM_VERSION_MAJOR >= 14
IRB.getInt32Ty(),
#endif
CTX_add);
val1 = IRB.CreateAdd(val1, CTX_load);
val2 = IRB.CreateAdd(val2, CTX_load);
}
result = IRB.CreateSelect(condition, val1, val2);
skip_next = 1;
inst += 2;
@ -1365,6 +1812,18 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
Value *val1 = ConstantInt::get(Int32Ty, ++afl_global_id);
Value *val2 = ConstantInt::get(Int32Ty, ++afl_global_id);
if (CTX_add) {
LoadInst *CTX_load = IRB.CreateLoad(
#if LLVM_VERSION_MAJOR >= 14
IRB.getInt32Ty(),
#endif
CTX_add);
val1 = IRB.CreateAdd(val1, CTX_load);
val2 = IRB.CreateAdd(val2, CTX_load);
}
x = IRB.CreateInsertElement(GuardPtr1, val1, (uint64_t)0);
y = IRB.CreateInsertElement(GuardPtr2, val2, (uint64_t)0);
@ -1372,6 +1831,18 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
val1 = ConstantInt::get(Int32Ty, ++afl_global_id);
val2 = ConstantInt::get(Int32Ty, ++afl_global_id);
/*if (CTX_add) { // already loaded I guess
LoadInst *CTX_load = IRB.CreateLoad(
#if LLVM_VERSION_MAJOR >= 14
IRB.getInt32Ty(),
#endif
CTX_add);
val1 = IRB.CreateAdd(val1, CTX_load);
val2 = IRB.CreateAdd(val2, CTX_load);
}*/
x = IRB.CreateInsertElement(GuardPtr1, val1, i);
y = IRB.CreateInsertElement(GuardPtr2, val2, i);
@ -1389,7 +1860,7 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
#endif
{
unhandled++;
++unhandled;
continue;
}
@ -1419,7 +1890,8 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
if (use_threadsafe_counters) {
IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One,
IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx,
One,
#if LLVM_VERSION_MAJOR >= 13
llvm::MaybeAlign(1),
#endif
@ -1452,17 +1924,24 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
}
skip_next = 1;
// fprintf(stderr, "Select out\n");
} else {
// fprintf(stderr, "Select skip\n");
skip_next = 0;
}
}
}
if (!instrument_ctx)
if (shouldInstrumentBlock(F, &BB, DT, PDT, Options))
BlocksToInstrument.push_back(&BB);
/*
for (auto &Inst : BB) {
if (Options.IndirectCalls) {
@ -1472,12 +1951,34 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
}
}
}*/
}
InjectCoverage(F, BlocksToInstrument, IsLeafFunc);
InjectCoverageForIndirectCalls(F, IndirCalls);
// InjectCoverageForIndirectCalls(F, IndirCalls);
/*if (debug)
fprintf(stderr, "Done instrumentation (%u-%u=%u %u-%u=%u)\n", inst,
inst_save, inst - inst_save, afl_global_id, save_global,
afl_global_id - save_global);*/
if (inst_in_this_func && call_counter > 1) {
if (inst_in_this_func != afl_global_id - save_global) {
fprintf(
stderr,
"BUG! inst_in_this_func %u != afl_global_id %u - save_global %u\n",
inst_in_this_func, afl_global_id, save_global);
exit(-1);
}
extra_ctx_inst += inst_in_this_func * (call_counter - 1);
afl_global_id += extra_ctx_inst;
}
}
@ -1603,6 +2104,34 @@ bool ModuleSanitizerCoverageLTO::InjectCoverage(
}
bool ModuleSanitizerCoverageLTO::Fake_InjectCoverage(
Function &F, ArrayRef<BasicBlock *> AllBlocks, bool IsLeafFunc) {
if (AllBlocks.empty()) return false;
for (size_t i = 0, N = AllBlocks.size(); i < N; i++) {
if (BlockList.size()) {
int skip = 0;
for (uint32_t k = 0; k < BlockList.size(); k++) {
if (AllBlocks[i] == BlockList[k]) { skip = 1; }
}
if (skip) continue;
}
++inst; // InjectCoverageAtBlock()
}
return true;
}
// On every indirect call we call a run-time function
// __sanitizer_cov_indir_call* with two parameters:
// - callee address,
@ -1610,6 +2139,7 @@ bool ModuleSanitizerCoverageLTO::InjectCoverage(
// The cache is used to speed up recording the caller-callee pairs.
// The address of the caller is passed implicitly via caller PC.
// CacheSize is encoded in the name of the run-time function.
/*
void ModuleSanitizerCoverageLTO::InjectCoverageForIndirectCalls(
Function &F, ArrayRef<Instruction *> IndirCalls) {
@ -1628,6 +2158,8 @@ void ModuleSanitizerCoverageLTO::InjectCoverageForIndirectCalls(
}
*/
void ModuleSanitizerCoverageLTO::InjectCoverageAtBlock(Function &F,
BasicBlock &BB,
size_t Idx,
@ -1674,6 +2206,19 @@ void ModuleSanitizerCoverageLTO::InjectCoverageAtBlock(Function &F,
/* Set the ID of the inserted basic block */
ConstantInt *CurLoc = ConstantInt::get(Int32Tyi, afl_global_id);
Value *val = CurLoc;
if (CTX_add) {
LoadInst *CTX_load = IRB.CreateLoad(
#if LLVM_VERSION_MAJOR >= 14
IRB.getInt32Ty(),
#endif
CTX_add);
ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(CTX_load);
val = IRB.CreateAdd(CurLoc, CTX_load);
}
/* Load SHM pointer */
@ -1681,13 +2226,13 @@ void ModuleSanitizerCoverageLTO::InjectCoverageAtBlock(Function &F,
if (map_addr) {
MapPtrIdx = IRB.CreateGEP(Int8Ty, MapPtrFixed, CurLoc);
MapPtrIdx = IRB.CreateGEP(Int8Ty, MapPtrFixed, val);
} else {
LoadInst *MapPtr = IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr);
ModuleSanitizerCoverageLTO::SetNoSanitizeMetadata(MapPtr);
MapPtrIdx = IRB.CreateGEP(Int8Ty, MapPtr, CurLoc);
MapPtrIdx = IRB.CreateGEP(Int8Ty, MapPtr, val);
}
@ -1722,12 +2267,10 @@ void ModuleSanitizerCoverageLTO::InjectCoverageAtBlock(Function &F,
// done :)
inst++;
++inst;
// AFL++ END
/*
XXXXXXXXXXXXXXXXXXX
auto GuardPtr = IRB.CreateIntToPtr(
IRB.CreateAdd(IRB.CreatePointerCast(FunctionGuardArray, IntptrTy),
ConstantInt::get(IntptrTy, Idx * 4)),

View File

@ -195,7 +195,7 @@ class ModuleSanitizerCoverageAFL
SanitizerCoverageOptions Options;
uint32_t instr = 0, selects = 0, unhandled = 0;
uint32_t instr = 0, selects = 0, unhandled = 0, dump_cc = 0;
GlobalVariable *AFLMapPtr = NULL;
ConstantInt *One = NULL;
ConstantInt *Zero = NULL;
@ -330,6 +330,8 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
if (getenv("AFL_DEBUG")) { debug = 1; }
if (getenv("AFL_DUMP_CYCLOMATIC_COMPLEXITY")) { dump_cc = 1; }
if ((isatty(2) && !getenv("AFL_QUIET")) || debug) {
SAYF(cCYA "SanitizerCoveragePCGUARD" VERSION cRST "\n");
@ -638,6 +640,8 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
// InjectTraceForCmp(F, CmpTraceTargets);
// InjectTraceForSwitch(F, SwitchTraceTargets);
if (dump_cc) { calcCyclomaticComplexity(&F); }
}
GlobalVariable *ModuleSanitizerCoverageAFL::CreateFunctionLocalArrayInSection(

View File

@ -87,6 +87,10 @@ __attribute__((weak)) void __sanitizer_symbolize_pc(void *, const char *fmt,
#include <sys/mman.h>
#include <fcntl.h>
#ifdef AFL_PERSISTENT_RECORD
#include "afl-persistent-replay.h"
#endif
/* Globals needed by the injected instrumentation. The __afl_area_initial region
is used for instrumentation output before __afl_map_shm() has a chance to
run. It will end up as .comm, so it shouldn't be too wasteful. */
@ -186,6 +190,8 @@ __thread u32 __afl_prev_ctx;
struct cmp_map *__afl_cmp_map;
struct cmp_map *__afl_cmp_map_backup;
static u8 __afl_cmplog_max_len = 32; // 16-32
/* Child pid? */
static s32 child_pid;
@ -264,7 +270,7 @@ static void send_forkserver_error(int error) {
u32 status;
if (!error || error > 0xffff) return;
status = (FS_OPT_ERROR | FS_OPT_SET_ERROR(error));
status = (FS_NEW_ERROR | error);
if (write(FORKSRV_FD + 1, (char *)&status, 4) != 4) { return; }
}
@ -367,23 +373,6 @@ static void __afl_map_shm(void) {
if ((ptr = getenv("AFL_MAP_SIZE")) != NULL) { val = atoi(ptr); }
if (val < __afl_final_loc) {
if (__afl_final_loc > FS_OPT_MAX_MAPSIZE) {
if (!getenv("AFL_QUIET"))
fprintf(stderr,
"Error: AFL++ tools *require* to set AFL_MAP_SIZE to %u "
"to be able to run this instrumented program!\n",
__afl_final_loc);
if (id_str) {
send_forkserver_error(FS_ERROR_MAP_SIZE);
exit(-1);
}
} else {
if (__afl_final_loc > MAP_INITIAL_SIZE && !getenv("AFL_QUIET")) {
fprintf(stderr,
@ -400,17 +389,6 @@ static void __afl_map_shm(void) {
}
} else {
if (getenv("AFL_DUMP_MAP_SIZE")) {
printf("%u\n", MAP_SIZE);
exit(-1);
}
}
if (__afl_sharedmem_fuzzing && (!id_str || !getenv(SHM_FUZZ_ENV_VAR) ||
fcntl(FORKSRV_FD, F_GETFD) == -1 ||
fcntl(FORKSRV_FD + 1, F_GETFD) == -1)) {
@ -474,14 +452,13 @@ static void __afl_map_shm(void) {
if (__afl_debug) {
fprintf(
stderr,
fprintf(stderr,
"DEBUG: (1) id_str %s, __afl_area_ptr %p, __afl_area_initial %p, "
"__afl_area_ptr_dummy %p, __afl_map_addr 0x%llx, MAP_SIZE %u, "
"__afl_final_loc %u, __afl_map_size %u, max_size_forkserver %u/0x%x\n",
id_str == NULL ? "<null>" : id_str, __afl_area_ptr, __afl_area_initial,
__afl_area_ptr_dummy, __afl_map_addr, MAP_SIZE, __afl_final_loc,
__afl_map_size, FS_OPT_MAX_MAPSIZE, FS_OPT_MAX_MAPSIZE);
"__afl_final_loc %u, __afl_map_size %u\n",
id_str == NULL ? "<null>" : id_str, __afl_area_ptr,
__afl_area_initial, __afl_area_ptr_dummy, __afl_map_addr, MAP_SIZE,
__afl_final_loc, __afl_map_size);
}
@ -639,12 +616,10 @@ static void __afl_map_shm(void) {
fprintf(stderr,
"DEBUG: (2) id_str %s, __afl_area_ptr %p, __afl_area_initial %p, "
"__afl_area_ptr_dummy %p, __afl_map_addr 0x%llx, MAP_SIZE "
"%u, __afl_final_loc %u, __afl_map_size %u, "
"max_size_forkserver %u/0x%x\n",
"%u, __afl_final_loc %u, __afl_map_size %u",
id_str == NULL ? "<null>" : id_str, __afl_area_ptr,
__afl_area_initial, __afl_area_ptr_dummy, __afl_map_addr, MAP_SIZE,
__afl_final_loc, __afl_map_size, FS_OPT_MAX_MAPSIZE,
FS_OPT_MAX_MAPSIZE);
__afl_final_loc, __afl_map_size);
}
@ -761,6 +736,19 @@ static void __afl_map_shm(void) {
#endif // __AFL_CODE_COVERAGE
if (!__afl_cmp_map && getenv("AFL_CMPLOG_DEBUG")) {
__afl_cmp_map_backup = __afl_cmp_map = malloc(sizeof(struct cmp_map));
}
if (getenv("AFL_CMPLOG_MAX_LEN")) {
int tmp = atoi(getenv("AFL_CMPLOG_MAX_LEN"));
if (tmp >= 16 && tmp <= 32) { __afl_cmplog_max_len = tmp; }
}
}
/* unmap SHM. */
@ -855,242 +843,6 @@ void write_error_with_location(char *text, char *filename, int linenumber) {
}
#ifdef __linux__
static void __afl_start_snapshots(void) {
static u8 tmp[4] = {0, 0, 0, 0};
u32 status = 0;
u32 already_read_first = 0;
u32 was_killed;
u8 child_stopped = 0;
void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL);
/* Phone home and tell the parent that we're OK. If parent isn't there,
assume we're not running in forkserver mode and just execute program. */
status |= (FS_OPT_ENABLED | FS_OPT_SNAPSHOT | FS_OPT_NEWCMPLOG);
if (__afl_sharedmem_fuzzing) { status |= FS_OPT_SHDMEM_FUZZ; }
if (__afl_map_size <= FS_OPT_MAX_MAPSIZE)
status |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE);
if (__afl_dictionary_len && __afl_dictionary) { status |= FS_OPT_AUTODICT; }
memcpy(tmp, &status, 4);
if (write(FORKSRV_FD + 1, tmp, 4) != 4) { return; }
if (__afl_sharedmem_fuzzing || (__afl_dictionary_len && __afl_dictionary)) {
if (read(FORKSRV_FD, &was_killed, 4) != 4) {
write_error("read to afl-fuzz");
_exit(1);
}
if (__afl_debug) {
fprintf(stderr, "DEBUG: target forkserver recv: %08x\n", was_killed);
}
if ((was_killed & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) ==
(FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) {
__afl_map_shm_fuzz();
}
if ((was_killed & (FS_OPT_ENABLED | FS_OPT_AUTODICT)) ==
(FS_OPT_ENABLED | FS_OPT_AUTODICT) &&
__afl_dictionary_len && __afl_dictionary) {
// great lets pass the dictionary through the forkserver FD
u32 len = __afl_dictionary_len, offset = 0;
s32 ret;
if (write(FORKSRV_FD + 1, &len, 4) != 4) {
write(2, "Error: could not send dictionary len\n",
strlen("Error: could not send dictionary len\n"));
_exit(1);
}
while (len != 0) {
ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len);
if (ret < 1) {
write(2, "Error: could not send dictionary\n",
strlen("Error: could not send dictionary\n"));
_exit(1);
}
len -= ret;
offset += ret;
}
} else {
// uh this forkserver does not understand extended option passing
// or does not want the dictionary
if (!__afl_fuzz_ptr) already_read_first = 1;
}
}
while (1) {
int status;
if (already_read_first) {
already_read_first = 0;
} else {
/* Wait for parent by reading from the pipe. Abort if read fails. */
if (read(FORKSRV_FD, &was_killed, 4) != 4) {
write_error("reading from afl-fuzz");
_exit(1);
}
}
#ifdef _AFL_DOCUMENT_MUTATIONS
if (__afl_fuzz_ptr) {
static uint32_t counter = 0;
char fn[32];
sprintf(fn, "%09u:forkserver", counter);
s32 fd_doc = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION);
if (fd_doc >= 0) {
if (write(fd_doc, __afl_fuzz_ptr, *__afl_fuzz_len) != *__afl_fuzz_len) {
fprintf(stderr, "write of mutation file failed: %s\n", fn);
unlink(fn);
}
close(fd_doc);
}
counter++;
}
#endif
/* If we stopped the child in persistent mode, but there was a race
condition and afl-fuzz already issued SIGKILL, write off the old
process. */
if (child_stopped && was_killed) {
child_stopped = 0;
if (waitpid(child_pid, &status, 0) < 0) {
write_error("child_stopped && was_killed");
_exit(1); // TODO why exit?
}
}
if (!child_stopped) {
/* Once woken up, create a clone of our process. */
child_pid = fork();
if (child_pid < 0) {
write_error("fork");
_exit(1);
}
/* In child process: close fds, resume execution. */
if (!child_pid) {
//(void)nice(-20); // does not seem to improve
signal(SIGCHLD, old_sigchld_handler);
signal(SIGTERM, old_sigterm_handler);
close(FORKSRV_FD);
close(FORKSRV_FD + 1);
if (!afl_snapshot_take(AFL_SNAPSHOT_MMAP | AFL_SNAPSHOT_FDS |
AFL_SNAPSHOT_REGS | AFL_SNAPSHOT_EXIT)) {
raise(SIGSTOP);
}
__afl_area_ptr[0] = 1;
memset(__afl_prev_loc, 0, NGRAM_SIZE_MAX * sizeof(PREV_LOC_T));
return;
}
} else {
/* Special handling for persistent mode: if the child is alive but
currently stopped, simply restart it with SIGCONT. */
kill(child_pid, SIGCONT);
child_stopped = 0;
}
/* In parent process: write PID to pipe, then wait for child. */
if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) {
write_error("write to afl-fuzz");
_exit(1);
}
if (waitpid(child_pid, &status, WUNTRACED) < 0) {
write_error("waitpid");
_exit(1);
}
/* In persistent mode, the child stops itself with SIGSTOP to indicate
a successful run. In this case, we want to wake it up without forking
again. */
if (WIFSTOPPED(status)) child_stopped = 1;
/* Relay wait status to pipe, then loop back. */
if (write(FORKSRV_FD + 1, &status, 4) != 4) {
write_error("writing to afl-fuzz");
_exit(1);
}
}
}
#endif
/* Fork server logic. */
static void __afl_start_forkserver(void) {
@ -1103,76 +855,54 @@ static void __afl_start_forkserver(void) {
old_sigterm_handler = orig_action.sa_handler;
signal(SIGTERM, at_exit);
#ifdef __linux__
if (/*!is_persistent &&*/ !__afl_cmp_map && !getenv("AFL_NO_SNAPSHOT") &&
afl_snapshot_init() >= 0) {
__afl_start_snapshots();
return;
}
#endif
u8 tmp[4] = {0, 0, 0, 0};
u32 status_for_fsrv = 0;
u32 already_read_first = 0;
u32 was_killed;
u32 version = 0x41464c00 + FS_NEW_VERSION_MAX;
u32 tmp = version ^ 0xffffffff, status2, status = version;
u8 *msg = (u8 *)&status;
u8 *reply = (u8 *)&status2;
u8 child_stopped = 0;
void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL);
if (__afl_map_size <= FS_OPT_MAX_MAPSIZE) {
status_for_fsrv |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE);
}
if (__afl_dictionary_len && __afl_dictionary) {
status_for_fsrv |= FS_OPT_AUTODICT;
}
if (__afl_sharedmem_fuzzing) { status_for_fsrv |= FS_OPT_SHDMEM_FUZZ; }
if (status_for_fsrv) {
status_for_fsrv |= (FS_OPT_ENABLED | FS_OPT_NEWCMPLOG);
}
memcpy(tmp, &status_for_fsrv, 4);
/* Phone home and tell the parent that we're OK. If parent isn't there,
assume we're not running in forkserver mode and just execute program. */
if (write(FORKSRV_FD + 1, tmp, 4) != 4) { return; }
// return because possible non-forkserver usage
if (write(FORKSRV_FD + 1, msg, 4) != 4) { return; }
__afl_connected = 1;
if (read(FORKSRV_FD, reply, 4) != 4) { _exit(1); }
if (tmp != status2) {
if (__afl_sharedmem_fuzzing || (__afl_dictionary_len && __afl_dictionary)) {
if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1);
if (__afl_debug) {
fprintf(stderr, "DEBUG: target forkserver recv: %08x\n", was_killed);
write_error("wrong forkserver message from AFL++ tool");
_exit(1);
}
if ((was_killed & (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) ==
(FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) {
// send the set/requested options to forkserver
status = FS_NEW_OPT_MAPSIZE; // we always send the map size
if (__afl_sharedmem_fuzzing) { status |= FS_NEW_OPT_SHDMEM_FUZZ; }
if (__afl_dictionary_len && __afl_dictionary) {
__afl_map_shm_fuzz();
status |= FS_NEW_OPT_AUTODICT;
}
if ((was_killed & (FS_OPT_ENABLED | FS_OPT_AUTODICT)) ==
(FS_OPT_ENABLED | FS_OPT_AUTODICT) &&
__afl_dictionary_len && __afl_dictionary) {
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
// great lets pass the dictionary through the forkserver FD
// Now send the parameters for the set options, increasing by option number
// FS_NEW_OPT_MAPSIZE - we always send the map size
status = __afl_map_size;
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
// FS_NEW_OPT_SHDMEM_FUZZ - no data
// FS_NEW_OPT_AUTODICT - send autodictionary
if (__afl_dictionary_len && __afl_dictionary) {
// pass the dictionary through the forkserver FD
u32 len = __afl_dictionary_len, offset = 0;
if (write(FORKSRV_FD + 1, &len, 4) != 4) {
@ -1190,8 +920,7 @@ static void __afl_start_forkserver(void) {
if (ret < 1) {
write(2, "Error: could not send dictionary\n",
strlen("Error: could not send dictionary\n"));
write_error("could not send dictionary");
_exit(1);
}
@ -1201,15 +930,17 @@ static void __afl_start_forkserver(void) {
}
} else {
// uh this forkserver does not understand extended option passing
// or does not want the dictionary
if (!__afl_fuzz_ptr) already_read_first = 1;
}
}
// send welcome message as final message
status = version;
if (write(FORKSRV_FD + 1, msg, 4) != 4) { _exit(1); }
// END forkserver handshake
__afl_connected = 1;
if (__afl_sharedmem_fuzzing) { __afl_map_shm_fuzz(); }
while (1) {
@ -1225,7 +956,7 @@ static void __afl_start_forkserver(void) {
if (read(FORKSRV_FD, &was_killed, 4) != 4) {
// write_error("read from afl-fuzz");
write_error("read from AFL++ tool");
_exit(1);
}
@ -1354,6 +1085,10 @@ int __afl_persistent_loop(unsigned int max_cnt) {
static u8 first_pass = 1;
static u32 cycle_cnt;
#ifdef AFL_PERSISTENT_RECORD
char tcase[PATH_MAX];
#endif
if (first_pass) {
/* Make sure that every iteration of __AFL_LOOP() starts with a clean slate.
@ -1365,14 +1100,59 @@ int __afl_persistent_loop(unsigned int max_cnt) {
__afl_area_ptr[0] = 1;
memset(__afl_prev_loc, 0, NGRAM_SIZE_MAX * sizeof(PREV_LOC_T));
cycle_cnt = max_cnt;
first_pass = 0;
__afl_selective_coverage_temp = 1;
#ifdef AFL_PERSISTENT_RECORD
if (unlikely(is_replay_record)) {
cycle_cnt = replay_record_cnt;
goto persistent_record;
} else
#endif
{
cycle_cnt = max_cnt;
}
return 1;
} else if (--cycle_cnt) {
#ifdef AFL_PERSISTENT_RECORD
if (unlikely(is_replay_record)) {
persistent_record:
snprintf(tcase, PATH_MAX, "%s/%s",
replay_record_dir ? replay_record_dir : "./",
record_list[replay_record_cnt - cycle_cnt]->d_name);
#ifdef AFL_PERSISTENT_REPLAY_ARGPARSE
if (unlikely(record_arg)) {
*record_arg = tcase;
} else
#endif // AFL_PERSISTENT_REPLAY_ARGPARSE
{
int fd = open(tcase, O_RDONLY);
dup2(fd, 0);
close(fd);
}
return 1;
}
#endif
raise(SIGSTOP);
__afl_area_ptr[0] = 1;
@ -1837,7 +1617,7 @@ void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
}
if (pc_filter) {
if (pc_filter && !mod_info->next) {
char PcDescr[1024];
// This function is a part of the sanitizer run-time.
@ -1864,7 +1644,8 @@ void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
}
if (__afl_filter_pcs && strstr(mod_info->name, __afl_filter_pcs_module)) {
if (__afl_filter_pcs && !mod_info->next &&
strstr(mod_info->name, __afl_filter_pcs_module)) {
u32 result_index;
if (locate_in_pcs(PC, &result_index)) {
@ -1889,7 +1670,7 @@ void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
}
mod_info->mapped = 1;
if (__afl_pcmap_ptr) { mod_info->mapped = 1; }
if (__afl_debug) {
@ -2181,7 +1962,8 @@ void __cmplog_ins_hook1(uint8_t arg1, uint8_t arg2, uint8_t attr) {
void __cmplog_ins_hook2(uint16_t arg1, uint16_t arg2, uint8_t attr) {
if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
if (likely(!__afl_cmp_map)) return;
if (unlikely(arg1 == arg2)) return;
uintptr_t k = (uintptr_t)__builtin_return_address(0);
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
@ -2219,7 +2001,8 @@ void __cmplog_ins_hook4(uint32_t arg1, uint32_t arg2, uint8_t attr) {
// fprintf(stderr, "hook4 arg0=%x arg1=%x attr=%u\n", arg1, arg2, attr);
if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
if (likely(!__afl_cmp_map)) return;
if (unlikely(arg1 == arg2)) return;
uintptr_t k = (uintptr_t)__builtin_return_address(0);
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
@ -2257,7 +2040,8 @@ void __cmplog_ins_hook8(uint64_t arg1, uint64_t arg2, uint8_t attr) {
// fprintf(stderr, "hook8 arg0=%lx arg1=%lx attr=%u\n", arg1, arg2, attr);
if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
if (likely(!__afl_cmp_map)) return;
if (unlikely(arg1 == arg2)) return;
uintptr_t k = (uintptr_t)__builtin_return_address(0);
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
@ -2300,7 +2084,8 @@ void __cmplog_ins_hookN(uint128_t arg1, uint128_t arg2, uint8_t attr,
// (u64)(arg1 >> 64), (u64)arg1, (u64)(arg2 >> 64), (u64)arg2, size + 1,
// attr);
if (unlikely(!__afl_cmp_map || arg1 == arg2)) return;
if (likely(!__afl_cmp_map)) return;
if (unlikely(arg1 == arg2 || size > __afl_cmplog_max_len)) return;
uintptr_t k = (uintptr_t)__builtin_return_address(0);
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
@ -2344,6 +2129,7 @@ void __cmplog_ins_hookN(uint128_t arg1, uint128_t arg2, uint8_t attr,
void __cmplog_ins_hook16(uint128_t arg1, uint128_t arg2, uint8_t attr) {
if (likely(!__afl_cmp_map)) return;
if (16 > __afl_cmplog_max_len) return;
uintptr_t k = (uintptr_t)__builtin_return_address(0);
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
@ -2537,13 +2323,25 @@ void __cmplog_rtn_hook_strn(u8 *ptr1, u8 *ptr2, u64 len) {
// fprintf(stderr, "RTN1 %p %p %u\n", ptr1, ptr2, len);
if (likely(!__afl_cmp_map)) return;
if (unlikely(!len)) return;
int len0 = MIN(len, 31);
if (unlikely(!len || len > __afl_cmplog_max_len)) return;
int len0 = MIN(len, 32);
int len1 = strnlen(ptr1, len0);
if (len1 < 31) len1 = area_is_valid(ptr1, len1 + 1);
if (len1 <= 32) len1 = area_is_valid(ptr1, len1 + 1);
if (len1 > __afl_cmplog_max_len) len1 = 0;
int len2 = strnlen(ptr2, len0);
if (len2 < 31) len2 = area_is_valid(ptr2, len2 + 1);
int l = MAX(len1, len2);
if (len2 <= 32) len2 = area_is_valid(ptr2, len2 + 1);
if (len2 > __afl_cmplog_max_len) len2 = 0;
int l;
if (!len1)
l = len2;
else if (!len2)
l = len1;
else
l = MAX(len1, len2);
if (l < 2) return;
uintptr_t k = (uintptr_t)__builtin_return_address(0);
@ -2587,10 +2385,18 @@ void __cmplog_rtn_hook_str(u8 *ptr1, u8 *ptr2) {
// fprintf(stderr, "RTN1 %p %p\n", ptr1, ptr2);
if (likely(!__afl_cmp_map)) return;
if (unlikely(!ptr1 || !ptr2)) return;
int len1 = strnlen(ptr1, 30) + 1;
int len2 = strnlen(ptr2, 30) + 1;
int l = MAX(len1, len2);
if (l < 3) return;
int len1 = strnlen(ptr1, 31) + 1;
int len2 = strnlen(ptr2, 31) + 1;
if (len1 > __afl_cmplog_max_len) len1 = 0;
if (len2 > __afl_cmplog_max_len) len2 = 0;
int l;
if (!len1)
l = len2;
else if (!len2)
l = len1;
else
l = MAX(len1, len2);
if (l < 2) return;
uintptr_t k = (uintptr_t)__builtin_return_address(0);
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));
@ -2632,7 +2438,7 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
/*
u32 i;
if (area_is_valid(ptr1, 31) <= 0 || area_is_valid(ptr2, 31) <= 0) return;
if (area_is_valid(ptr1, 32) <= 0 || area_is_valid(ptr2, 32) <= 0) return;
fprintf(stderr, "rtn arg0=");
for (i = 0; i < 32; i++)
fprintf(stderr, "%02x", ptr1[i]);
@ -2645,10 +2451,10 @@ void __cmplog_rtn_hook(u8 *ptr1, u8 *ptr2) {
// fprintf(stderr, "RTN1 %p %p\n", ptr1, ptr2);
if (likely(!__afl_cmp_map)) return;
int l1, l2;
if ((l1 = area_is_valid(ptr1, 31)) <= 0 ||
(l2 = area_is_valid(ptr2, 31)) <= 0)
if ((l1 = area_is_valid(ptr1, 32)) <= 0 ||
(l2 = area_is_valid(ptr2, 32)) <= 0)
return;
int len = MIN(31, MIN(l1, l2));
int len = MIN(__afl_cmplog_max_len, MIN(l1, l2));
// fprintf(stderr, "RTN2 %u\n", len);
uintptr_t k = (uintptr_t)__builtin_return_address(0);
@ -2697,7 +2503,7 @@ void __cmplog_rtn_hook_n(u8 *ptr1, u8 *ptr2, u64 len) {
#if 0
/*
u32 i;
if (area_is_valid(ptr1, 31) <= 0 || area_is_valid(ptr2, 31) <= 0) return;
if (area_is_valid(ptr1, 32) <= 0 || area_is_valid(ptr2, 32) <= 0) return;
fprintf(stderr, "rtn_n len=%u arg0=", len);
for (i = 0; i < len; i++)
fprintf(stderr, "%02x", ptr1[i]);
@ -2709,12 +2515,15 @@ void __cmplog_rtn_hook_n(u8 *ptr1, u8 *ptr2, u64 len) {
// fprintf(stderr, "RTN1 %p %p %u\n", ptr1, ptr2, len);
if (likely(!__afl_cmp_map)) return;
if (unlikely(!len)) return;
int l = MIN(31, len);
if (!len) return;
int l = MIN(32, len), l1, l2;
if ((l = area_is_valid(ptr1, l)) <= 0 || (l = area_is_valid(ptr2, l)) <= 0)
if ((l1 = area_is_valid(ptr1, l)) <= 0 || (l2 = area_is_valid(ptr2, l)) <= 0)
return;
len = MIN(l1, l2);
if (len > __afl_cmplog_max_len) return;
// fprintf(stderr, "RTN2 %u\n", l);
uintptr_t k = (uintptr_t)__builtin_return_address(0);
k = (uintptr_t)(default_hash((u8 *)&k, sizeof(uintptr_t)) & (CMP_MAP_W - 1));

View File

@ -180,19 +180,19 @@ struct afl_cmptrs_pass : afl_base_pass {
c = DECL_CONTEXT(c);
if (c && TREE_CODE(c) != TRANSLATION_UNIT_DECL) return false;
/* Check that the first nonstatic data member of the record type
/* Check that the first nonstatic named data member of the record type
is named _M_dataplus. */
for (c = TYPE_FIELDS(t); c; c = DECL_CHAIN(c))
if (TREE_CODE(c) == FIELD_DECL) break;
if (TREE_CODE(c) == FIELD_DECL && DECL_NAME(c)) break;
if (!c || !integer_zerop(DECL_FIELD_BIT_OFFSET(c)) ||
strcmp(IDENTIFIER_POINTER(DECL_NAME(c)), "_M_dataplus") != 0)
return false;
/* Check that the second nonstatic data member of the record type
/* Check that the second nonstatic named data member of the record type
is named _M_string_length. */
tree f2;
for (f2 = DECL_CHAIN(c); f2; f2 = DECL_CHAIN(f2))
if (TREE_CODE(f2) == FIELD_DECL) break;
if (TREE_CODE(f2) == FIELD_DECL && DECL_NAME(f2)) break;
if (!f2 /* No need to check this field's offset. */
|| strcmp(IDENTIFIER_POINTER(DECL_NAME(f2)), "_M_string_length") != 0)
return false;
@ -208,9 +208,12 @@ struct afl_cmptrs_pass : afl_base_pass {
strcmp(IDENTIFIER_POINTER(TYPE_IDENTIFIER(c)), "_Alloc_hider") != 0)
return false;
/* And its first data member is named _M_p. */
/* And its first nonstatic named data member should be named _M_p.
There may be (unnamed) subobjects from empty base classes. We
skip the subobjects, then check the offset of the first data
member. */
for (c = TYPE_FIELDS(c); c; c = DECL_CHAIN(c))
if (TREE_CODE(c) == FIELD_DECL) break;
if (TREE_CODE(c) == FIELD_DECL && DECL_NAME(c)) break;
if (!c || !integer_zerop(DECL_FIELD_BIT_OFFSET(c)) ||
strcmp(IDENTIFIER_POINTER(DECL_NAME(c)), "_M_p") != 0)
return false;

View File

@ -26,6 +26,51 @@ static std::list<std::string> allowListFunctions;
static std::list<std::string> denyListFiles;
static std::list<std::string> denyListFunctions;
unsigned int calcCyclomaticComplexity(llvm::Function *F) {
unsigned int numBlocks = 0;
unsigned int numEdges = 0;
unsigned int numCalls = 0;
// Iterate through each basic block in the function
for (BasicBlock &BB : *F) {
// count all nodes == basic blocks
numBlocks++;
// Count the number of successors (outgoing edges)
for (BasicBlock *Succ : successors(&BB)) {
// count edges for CC
numEdges++;
(void)(Succ);
}
for (Instruction &I : BB) {
// every call is also an edge, so we need to count the calls too
if (isa<CallInst>(&I) || isa<InvokeInst>(&I)) { numCalls++; }
}
}
// Cyclomatic Complexity V(G) = E - N + 2P
// For a single function, P (number of connected components) is 1
// Calls are considered to be an edge
unsigned int CC = 2 + numCalls + numEdges - numBlocks;
// if (debug) {
fprintf(stderr, "CyclomaticComplexity for %s: %u\n",
F->getName().str().c_str(), CC);
//}
return CC;
}
char *getBBName(const llvm::BasicBlock *BB) {
static char *name;
@ -91,7 +136,11 @@ bool isIgnoreFunction(const llvm::Function *F) {
for (auto const &ignoreListFunc : ignoreList) {
#if LLVM_VERSION_MAJOR >= 19
if (F->getName().starts_with(ignoreListFunc)) { return true; }
#else
if (F->getName().startswith(ignoreListFunc)) { return true; }
#endif
}

View File

@ -55,6 +55,7 @@ void initInstrumentList();
bool isInInstrumentList(llvm::Function *F, std::string Filename);
unsigned long long int calculateCollisions(uint32_t edges);
void scanForDangerousFunctions(llvm::Module *M);
unsigned int calcCyclomaticComplexity(llvm::Function *F);
#ifndef IS_EXTERN
#define IS_EXTERN

View File

@ -746,7 +746,7 @@ bool AFLdict2filePass::runOnModule(Module &M) {
auto PA = PreservedAnalyses::all();
return PA;
#else
return true;
return false;
#endif
}

View File

@ -128,7 +128,11 @@ llvmGetPassPluginInfo() {
#if LLVM_VERSION_MAJOR <= 13
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
#if LLVM_VERSION_MAJOR >= 16
PB.registerOptimizerEarlyEPCallback(
#else
PB.registerOptimizerLastEPCallback(
#endif
[](ModulePassManager &MPM, OptimizationLevel OL) {
MPM.addPass(AFLCoverage());
@ -212,10 +216,6 @@ bool AFLCoverage::runOnModule(Module &M) {
u32 rand_seed;
unsigned int cur_loc = 0;
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
auto PA = PreservedAnalyses::all();
#endif
/* Setup random() so we get Actually Random(TM) outputs from AFL_R() */
gettimeofday(&tv, &tz);
rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
@ -1081,7 +1081,7 @@ bool AFLCoverage::runOnModule(Module &M) {
}
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
return PA;
return PreservedAnalyses();
#else
return true;
#endif

View File

@ -680,13 +680,16 @@ bool CmpLogInstructions::runOnModule(Module &M) {
printf("Running cmplog-instructions-pass by andreafioraldi@gmail.com\n");
else
be_quiet = 1;
hookInstrs(M);
bool ret = hookInstrs(M);
verifyModule(M);
#if LLVM_MAJOR >= 11 /* use new pass manager */
if (ret == false)
return PreservedAnalyses::all();
else
return PreservedAnalyses();
#else
return true;
return ret;
#endif
}

View File

@ -758,16 +758,16 @@ bool CmpLogRoutines::runOnModule(Module &M) {
printf("Running cmplog-routines-pass by andreafioraldi@gmail.com\n");
else
be_quiet = 1;
hookRtns(M);
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
auto PA = PreservedAnalyses::all();
#endif
bool ret = hookRtns(M);
verifyModule(M);
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
return PA;
if (ret == false)
return PreservedAnalyses::all();
else
return PreservedAnalyses();
#else
return true;
return ret;
#endif
}

View File

@ -442,16 +442,16 @@ bool CmplogSwitches::runOnModule(Module &M) {
printf("Running cmplog-switches-pass by andreafioraldi@gmail.com\n");
else
be_quiet = 1;
hookInstrs(M);
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
auto PA = PreservedAnalyses::all();
#endif
bool ret = hookInstrs(M);
verifyModule(M);
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
return PA;
if (ret == false)
return PreservedAnalyses::all();
else
return PreservedAnalyses();
#else
return true;
return ret;
#endif
}

View File

@ -54,6 +54,12 @@
#define nullptr 0
#endif
#if LLVM_MAJOR >= 19
#define STARTSWITH starts_with
#else
#define STARTSWITH startswith
#endif
#include <set>
#include "afl-llvm-common.h"
@ -89,7 +95,7 @@ class CompareTransform : public ModulePass {
#endif
return "cmplog transform";
return "compcov transform";
}
@ -123,7 +129,11 @@ llvmGetPassPluginInfo() {
#if LLVM_VERSION_MAJOR <= 13
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
#if LLVM_VERSION_MAJOR >= 16
PB.registerOptimizerEarlyEPCallback(
#else
PB.registerOptimizerLastEPCallback(
#endif
[](ModulePassManager &MPM, OptimizationLevel OL) {
MPM.addPass(CompareTransform());
@ -226,38 +236,38 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
if (callInst->getCallingConv() != llvm::CallingConv::C) continue;
StringRef FuncName = Callee->getName();
isStrcmp &=
(!FuncName.compare("strcmp") || !FuncName.compare("xmlStrcmp") ||
(!FuncName.compare("strcmp") /*|| !FuncName.compare("xmlStrcmp") ||
!FuncName.compare("xmlStrEqual") ||
!FuncName.compare("curl_strequal") ||
!FuncName.compare("strcsequal") ||
!FuncName.compare("g_strcmp0"));
!FuncName.compare("g_strcmp0")*/);
isMemcmp &=
(!FuncName.compare("memcmp") || !FuncName.compare("bcmp") ||
!FuncName.compare("CRYPTO_memcmp") ||
!FuncName.compare("OPENSSL_memcmp") ||
!FuncName.compare("memcmp_const_time") ||
!FuncName.compare("memcmpct"));
isStrncmp &= (!FuncName.compare("strncmp") ||
isStrncmp &= (!FuncName.compare("strncmp")/* ||
!FuncName.compare("curl_strnequal") ||
!FuncName.compare("xmlStrncmp"));
!FuncName.compare("xmlStrncmp")*/);
isStrcasecmp &= (!FuncName.compare("strcasecmp") ||
!FuncName.compare("stricmp") ||
!FuncName.compare("ap_cstr_casecmp") ||
!FuncName.compare("OPENSSL_strcasecmp") ||
!FuncName.compare("xmlStrcasecmp") ||
/*!FuncName.compare("xmlStrcasecmp") ||
!FuncName.compare("g_strcasecmp") ||
!FuncName.compare("g_ascii_strcasecmp") ||
!FuncName.compare("Curl_strcasecompare") ||
!FuncName.compare("Curl_safe_strcasecompare") ||
!FuncName.compare("Curl_safe_strcasecompare") ||*/
!FuncName.compare("cmsstrcasecmp"));
isStrncasecmp &= (!FuncName.compare("strncasecmp") ||
!FuncName.compare("strnicmp") ||
!FuncName.compare("ap_cstr_casecmpn") ||
!FuncName.compare("OPENSSL_strncasecmp") ||
!FuncName.compare("OPENSSL_strncasecmp") /*||
!FuncName.compare("xmlStrncasecmp") ||
!FuncName.compare("g_ascii_strncasecmp") ||
!FuncName.compare("Curl_strncasecompare") ||
!FuncName.compare("g_strncasecmp"));
!FuncName.compare("g_strncasecmp")*/);
isIntMemcpy &= !FuncName.compare("llvm.memcpy.p0i8.p0i8.i64");
if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp &&
@ -461,8 +471,20 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
bool isCaseInsensitive = false;
bool needs_null = false;
bool success_is_one = false;
bool nullCheck = false;
Function *Callee = callInst->getCalledFunction();
/*
fprintf(stderr, "%s - %s - %s\n",
callInst->getParent()
->getParent()
->getParent()
->getName()
.str()
.c_str(),
callInst->getParent()->getParent()->getName().str().c_str(),
Callee ? Callee->getName().str().c_str() : "NULL");*/
if (Callee) {
if (!Callee->getName().compare("memcmp") ||
@ -516,6 +538,11 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
}
if (!isSizedcmp) needs_null = true;
if (Callee->getName().STARTSWITH("g_") ||
Callee->getName().STARTSWITH("curl_") ||
Callee->getName().STARTSWITH("Curl_") ||
Callee->getName().STARTSWITH("xml"))
nullCheck = true;
Value *sizedValue = isSizedcmp ? callInst->getArgOperand(2) : NULL;
bool isConstSized = sizedValue && isa<ConstantInt>(sizedValue);
@ -600,8 +627,10 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
/* split before the call instruction */
BasicBlock *bb = callInst->getParent();
BasicBlock *end_bb = bb->splitBasicBlock(BasicBlock::iterator(callInst));
BasicBlock *next_lenchk_bb = NULL;
if (nullCheck) { fprintf(stderr, "TODO: null check\n"); }
if (isSizedcmp && !isConstSized) {
next_lenchk_bb =
@ -746,6 +775,8 @@ bool CompareTransform::runOnModule(Module &M) {
#endif
bool ret = false;
if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL)
printf(
"Running compare-transform-pass by laf.intel@gmail.com, extended by "
@ -753,11 +784,7 @@ bool CompareTransform::runOnModule(Module &M) {
else
be_quiet = 1;
#if LLVM_MAJOR >= 11 /* use new pass manager */
auto PA = PreservedAnalyses::all();
#endif
transformCmps(M, true, true, true, true, true);
if (transformCmps(M, true, true, true, true, true) == true) ret = true;
verifyModule(M);
#if LLVM_MAJOR >= 11 /* use new pass manager */
@ -767,9 +794,18 @@ bool CompareTransform::runOnModule(Module &M) {
}*/
return PA;
if (ret == true) {
return PreservedAnalyses();
} else {
return PreservedAnalyses::all();
}
#else
return true;
return ret;
#endif
}

View File

@ -204,6 +204,8 @@ bool InjectionRoutines::hookRtns(Module &M) {
Function *FuncPtr;
#endif
bool ret = false;
/* iterate over all functions, bbs and instruction and add suitable calls */
for (auto &F : M) {
@ -281,6 +283,7 @@ bool InjectionRoutines::hookRtns(Module &M) {
IRBuilder<> IRB(callInst->getParent());
IRB.SetInsertPoint(callInst);
ret = true;
Value *parameter = callInst->getArgOperand(param);
@ -299,7 +302,7 @@ bool InjectionRoutines::hookRtns(Module &M) {
}
return true;
return ret;
}
@ -328,16 +331,16 @@ bool InjectionRoutines::runOnModule(Module &M) {
if (getenv("AFL_LLVM_INJECTIONS_LDAP")) { doLDAP = true; }
if (getenv("AFL_LLVM_INJECTIONS_XSS")) { doXSS = true; }
hookRtns(M);
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
auto PA = PreservedAnalyses::all();
#endif
bool ret = hookRtns(M);
verifyModule(M);
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
return PA;
if (ret == false)
return PreservedAnalyses::all();
else
return PreservedAnalyses();
#else
return true;
return ret;
#endif
}

View File

@ -1,7 +1,7 @@
/*
* Copyright 2016 laf-intel
* extended for floating point by Heiko Eißfeldt
* adapted to new pass manager by Heiko Eißfeldt
* extended for floating point by Heiko Eissfeldt
* adapted to new pass manager by Heiko Eissfeldt
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -189,7 +189,11 @@ llvmGetPassPluginInfo() {
#if LLVM_VERSION_MAJOR <= 13
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
#if LLVM_VERSION_MAJOR >= 16
PB.registerOptimizerEarlyEPCallback(
#else
PB.registerOptimizerLastEPCallback(
#endif
[](ModulePassManager &MPM, OptimizationLevel OL) {
MPM.addPass(SplitComparesTransform());
@ -262,8 +266,11 @@ bool SplitComparesTransform::simplifyFPCompares(Module &M) {
/* this is probably not needed but we do it anyway */
if (TyOp0 != TyOp1) { continue; }
if (TyOp0->isArrayTy() || TyOp0->isVectorTy()) { continue; }
int constants = 0;
if (llvm::isa<llvm::Constant>(op0)) { ++constants; }
if (llvm::isa<llvm::Constant>(op1)) { ++constants; }
if (constants != 1) { continue; }
fcomps.push_back(selectcmpInst);
@ -935,7 +942,7 @@ size_t SplitComparesTransform::nextPowerOfTwo(size_t in) {
/* splits fcmps into two nested fcmps with sign compare and the rest */
size_t SplitComparesTransform::splitFPCompares(Module &M) {
size_t count = 0;
size_t counts = 0;
LLVMContext &C = M.getContext();
@ -951,7 +958,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
} else {
return count;
return counts;
}
@ -1004,7 +1011,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
}
if (!fcomps.size()) { return count; }
if (!fcomps.size()) { return counts; }
IntegerType *Int1Ty = IntegerType::getInt1Ty(C);
@ -1690,11 +1697,11 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
#else
ReplaceInstWithInst(FcmpInst->getParent()->getInstList(), ii, PN);
#endif
++count;
++counts;
}
return count;
return counts;
}
@ -1743,10 +1750,6 @@ bool SplitComparesTransform::runOnModule(Module &M) {
}
#if LLVM_MAJOR >= 11
auto PA = PreservedAnalyses::all();
#endif
if (enableFPSplit) {
simplifyFPCompares(M);
@ -1778,15 +1781,13 @@ bool SplitComparesTransform::runOnModule(Module &M) {
auto op0 = CI->getOperand(0);
auto op1 = CI->getOperand(1);
if (!op0 || !op1) {
#if LLVM_MAJOR >= 11
return PA;
#else
return false;
#endif
}
// has to valid operands
if (!op0 || !op1) { continue; }
// has exactly one constant and one variable
int constants = 0;
if (dyn_cast<ConstantInt>(op0)) { ++constants; }
if (dyn_cast<ConstantInt>(op1)) { ++constants; }
if (constants != 1) { continue; }
auto iTy1 = dyn_cast<IntegerType>(op0->getType());
if (iTy1 && isa<IntegerType>(op1->getType())) {
@ -1814,6 +1815,8 @@ bool SplitComparesTransform::runOnModule(Module &M) {
}
bool ret = count == 0 ? false : true;
bool brokenDebug = false;
if (verifyModule(M, &errs()
#if LLVM_VERSION_MAJOR >= 4 || \
@ -1852,9 +1855,12 @@ bool SplitComparesTransform::runOnModule(Module &M) {
}*/
return PA;
if (ret == false)
return PreservedAnalyses::all();
else
return PreservedAnalyses();
#else
return true;
return ret;
#endif
}

View File

@ -137,7 +137,11 @@ llvmGetPassPluginInfo() {
#if LLVM_VERSION_MAJOR <= 13
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
#endif
#if LLVM_VERSION_MAJOR >= 16
PB.registerOptimizerEarlyEPCallback(
#else
PB.registerOptimizerLastEPCallback(
#endif
[](ModulePassManager &MPM, OptimizationLevel OL) {
MPM.addPass(SplitSwitchesTransform());
@ -516,11 +520,7 @@ bool SplitSwitchesTransform::runOnModule(Module &M) {
else
be_quiet = 1;
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
auto PA = PreservedAnalyses::all();
#endif
splitSwitches(M);
bool ret = splitSwitches(M);
verifyModule(M);
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
@ -530,9 +530,12 @@ bool SplitSwitchesTransform::runOnModule(Module &M) {
}*/
return PA;
if (ret == false)
return PreservedAnalyses::all();
else
return PreservedAnalyses();
#else
return true;
return ret;
#endif
}

BIN
model.bin Normal file

Binary file not shown.

View File

@ -1 +1 @@
e63c9af193
a6f0632a65

View File

@ -202,6 +202,8 @@ QEMU_CONF_FLAGS=" \
--disable-xfsctl \
--target-list="${CPU_TARGET}-linux-user" \
--without-default-devices \
--extra-cflags=-Wno-int-conversion \
--disable-werror \
"
if [ -n "${CROSS_PREFIX}" ]; then
@ -215,8 +217,10 @@ if [ "$STATIC" = "1" ]; then
echo Building STATIC binary
# static PIE causes https://github.com/AFLplusplus/AFLplusplus/issues/892
# plugin support requires dynamic linking
QEMU_CONF_FLAGS="$QEMU_CONF_FLAGS \
--static --disable-pie \
--disable-plugins \
--extra-cflags=-DAFL_QEMU_STATIC_BUILD=1 \
"
@ -241,7 +245,6 @@ if [ "$DEBUG" = "1" ]; then
--enable-debug-stack-usage \
--enable-debug-tcg \
--enable-qom-cast-debug \
--enable-werror \
"
else
@ -252,7 +255,6 @@ else
--disable-debug-tcg \
--disable-qom-cast-debug \
--disable-stack-protector \
--disable-werror \
--disable-docs \
"

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.

View File

@ -17,6 +17,10 @@
#define AFL_MAIN
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#include "common.h"
#include "config.h"
#include "types.h"
@ -32,7 +36,9 @@
#include <limits.h>
#include <assert.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#if (LLVM_MAJOR - 0 == 0)
#undef LLVM_MAJOR
@ -464,6 +470,8 @@ u8 *find_object(aflcc_state_t *aflcc, u8 *obj) {
*slash = 0;
tmp = alloc_printf("%s/%s", exepath, obj);
if (aflcc->debug) DEBUGF("Trying %s\n", tmp);
if (!access(tmp, R_OK)) { return tmp; }
ck_free(tmp);
@ -517,8 +525,8 @@ void find_built_deps(aflcc_state_t *aflcc) {
char *ptr = NULL;
#if defined(__x86_64__)
if ((ptr = find_object(aflcc, "as")) != NULL) {
#if defined(__x86_64__) || defined(__i386__)
if ((ptr = find_object(aflcc, "afl-as")) != NULL) {
#ifndef __APPLE__
// on OSX clang masquerades as GCC
@ -828,7 +836,8 @@ static void instrument_mode_old_environ(aflcc_state_t *aflcc) {
}
if (getenv("AFL_LLVM_CTX")) aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX;
if (getenv("AFL_LLVM_CALLER"))
if (getenv("AFL_LLVM_CALLER") || getenv("AFL_LLVM_LTO_CALLER") ||
getenv("AFL_LLVM_LTO_CTX"))
aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER;
if (getenv("AFL_LLVM_NGRAM_SIZE")) {
@ -1148,12 +1157,16 @@ static void instrument_opt_mode_exclude(aflcc_state_t *aflcc) {
}
if (aflcc->instrument_opt_mode && aflcc->compiler_mode != LLVM)
if (aflcc->instrument_opt_mode && aflcc->compiler_mode != LLVM &&
!((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER) &&
aflcc->compiler_mode == LTO))
FATAL("CTX, CALLER and NGRAM can only be used in LLVM mode");
if (aflcc->instrument_opt_mode &&
aflcc->instrument_opt_mode != INSTRUMENT_OPT_CODECOV &&
aflcc->instrument_mode != INSTRUMENT_CLASSIC)
aflcc->instrument_mode != INSTRUMENT_CLASSIC &&
!(aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER &&
aflcc->compiler_mode == LTO))
FATAL(
"CALLER, CTX and NGRAM instrumentation options can only be used with "
"the LLVM CLASSIC instrumentation mode.");
@ -1256,13 +1269,8 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) {
aflcc->instrument_mode == INSTRUMENT_PCGUARD) {
aflcc->lto_mode = 1;
// force CFG
// if (!aflcc->instrument_mode) {
aflcc->instrument_mode = INSTRUMENT_PCGUARD;
// }
} else if (aflcc->instrument_mode == INSTRUMENT_CLASSIC) {
aflcc->lto_mode = 1;
@ -1364,6 +1372,13 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) {
}
if (getenv("AFL_LLVM_DICT2FILE") &&
(getenv("AFL_LLVM_LAF_SPLIT_SWITCHES") ||
getenv("AFL_LLVM_LAF_SPLIT_COMPARES") ||
getenv("AFL_LLVM_LAF_SPLIT_FLOATS") ||
getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")))
FATAL("AFL_LLVM_DICT2FILE is incompatible with AFL_LLVM_LAF_*");
aflcc->cmplog_mode = getenv("AFL_CMPLOG") || getenv("AFL_LLVM_CMPLOG") ||
getenv("AFL_GCC_CMPLOG");
@ -1571,8 +1586,10 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) {
insert_param(aflcc,
"-D__AFL_FUZZ_INIT()="
"int __afl_sharedmem_fuzzing = 1;"
"extern unsigned int *__afl_fuzz_len;"
"extern unsigned char *__afl_fuzz_ptr;"
"extern __attribute__((visibility(\"default\"))) "
"unsigned int *__afl_fuzz_len;"
"extern __attribute__((visibility(\"default\"))) "
"unsigned char *__afl_fuzz_ptr;"
"unsigned char __afl_fuzz_alt[1048576];"
"unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;");
@ -1894,7 +1911,13 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) {
}
add_defs_fortify(aflcc, 0);
if (!aflcc->have_asan) { insert_param(aflcc, "-fsanitize=address"); }
if (!aflcc->have_asan) {
insert_param(aflcc, "-fsanitize=address");
insert_param(aflcc, "-fno-common");
}
aflcc->have_asan = 1;
} else if (getenv("AFL_USE_MSAN") || aflcc->have_msan) {
@ -2343,8 +2366,7 @@ static void add_aflpplib(aflcc_state_t *aflcc) {
insert_param(aflcc, afllib);
#ifdef __APPLE__
insert_param(aflcc, "-Wl,-undefined");
insert_param(aflcc, "dynamic_lookup");
insert_param(aflcc, "-Wl,-undefined,dynamic_lookup");
#endif
}
@ -2375,7 +2397,11 @@ void add_runtime(aflcc_state_t *aflcc) {
if (aflcc->plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) &&
strncmp(libdir, "/lib", 4)) {
#ifdef __APPLE__
u8 *libdir_opt = strdup("-Wl,-rpath," LLVM_LIBDIR);
#else
u8 *libdir_opt = strdup("-Wl,-rpath=" LLVM_LIBDIR);
#endif
insert_param(aflcc, libdir_opt);
}
@ -2457,13 +2483,60 @@ void add_runtime(aflcc_state_t *aflcc) {
*/
void add_assembler(aflcc_state_t *aflcc) {
u8 *afl_as = find_object(aflcc, "as");
u8 *afl_as = find_object(aflcc, "afl-as");
if (!afl_as) FATAL("Cannot find 'as' (symlink to 'afl-as').");
if (!afl_as) FATAL("Cannot find 'afl-as'.");
u8 *slash = strrchr(afl_as, '/');
if (slash) *slash = 0;
// Search for 'as' may be unreliable in some cases (see #2058)
// so use 'afl-as' instead, because 'as' is usually a symbolic link,
// or can be a renamed copy of 'afl-as' created in the same dir.
// Now we should verify if the compiler can find the 'as' we need.
#define AFL_AS_ERR "(should be a symlink or copy of 'afl-as')"
u8 *afl_as_dup = alloc_printf("%s/as", afl_as);
int fd = open(afl_as_dup, O_RDONLY);
if (fd < 0) { PFATAL("Unable to open '%s' " AFL_AS_ERR, afl_as_dup); }
struct stat st;
if (fstat(fd, &st) < 0) {
PFATAL("Unable to fstat '%s' " AFL_AS_ERR, afl_as_dup);
}
u32 f_len = st.st_size;
u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0);
if (f_data == MAP_FAILED) {
PFATAL("Unable to mmap file '%s' " AFL_AS_ERR, afl_as_dup);
}
close(fd);
// "AFL_AS" is a const str passed to getenv in afl-as.c
if (!memmem(f_data, f_len, "AFL_AS", strlen("AFL_AS") + 1)) {
FATAL(
"Looks like '%s' is not a valid symlink or copy of '%s/afl-as'. "
"It is a prerequisite to override system-wide 'as' for "
"instrumentation.",
afl_as_dup, afl_as);
}
if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); }
ck_free(afl_as_dup);
#undef AFL_AS_ERR
insert_param(aflcc, "-B");
insert_param(aflcc, afl_as);
@ -2770,7 +2843,7 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
" The best is LTO but it often needs RANLIB and AR settings outside "
"of afl-cc.\n\n");
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
#if LLVM_MAJOR >= 11 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
#define NATIVE_MSG \
" LLVM-NATIVE: use llvm's native PCGUARD instrumentation (less " \
"performant)\n"
@ -2917,11 +2990,12 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
" AFL_LLVM_DOCUMENT_IDS: write all edge IDs and the corresponding "
"functions\n"
" into this file (LTO mode)\n"
" AFL_LLVM_LTO_CALLER: activate CALLER/CTX instrumentation\n"
" AFL_LLVM_LTO_CALLER_DEPTH: skip how many empty functions\n"
" AFL_LLVM_LTO_DONTWRITEID: don't write the highest ID used to a "
"global var\n"
" AFL_LLVM_LTO_STARTID: from which ID to start counting from for "
"a "
"bb\n"
"a bb\n"
" AFL_REAL_LD: use this lld linker instead of the compiled in "
"path\n"
" AFL_LLVM_LTO_SKIPINIT: don't inject initialization code "

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
@ -34,6 +34,7 @@
#endif
#include <string.h>
#include <strings.h>
#include <time.h>
#include <math.h>
#include <sys/mman.h>
@ -86,9 +87,10 @@ void set_sanitizer_defaults() {
u8 *have_lsan_options = getenv("LSAN_OPTIONS");
u8 have_san_options = 0;
u8 default_options[1024] =
"detect_odr_violation=0:abort_on_error=1:symbolize=0:allocator_may_"
"return_null=1:handle_segv=0:handle_sigbus=0:handle_abort=0:handle_"
"sigfpe=0:handle_sigill=0:";
"detect_odr_violation=0:abort_on_error=1:symbolize=0:"
"allocator_may_return_null=1:handle_segv=0:handle_sigbus=0:"
"handle_abort=0:handle_sigfpe=0:handle_sigill=0:"
"detect_stack_use_after_return=0:check_initialization_order=0:";
if (have_asan_options || have_ubsan_options || have_msan_options ||
have_lsan_options) {
@ -484,7 +486,7 @@ u8 *find_afl_binary(u8 *own_loc, u8 *fname) {
if ((tmp = strrchr(fname, '.'))) {
if (!strcasecmp(tmp, ".so") || !strcasecmp(tmp, ".dylib")) { perm = R_OK; }
if (!strcasecmp(tmp, ".bin") || !strcasecmp(tmp, ".so") || !strcasecmp(tmp, ".dylib")) { perm = R_OK; }
}
@ -985,7 +987,7 @@ inline u64 get_cur_time(void) {
/* Get unix time in microseconds */
u64 get_cur_time_us(void) {
inline u64 get_cur_time_us(void) {
struct timeval tv;
struct timezone tz;

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com> and
Dominik Maier <mail@dmnk.co>
@ -27,6 +27,9 @@
*/
#include "config.h"
#ifdef AFL_PERSISTENT_RECORD
#include "afl-fuzz.h"
#endif
#include "types.h"
#include "debug.h"
#include "common.h"
@ -389,7 +392,7 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
while (1) {
uint32_t was_killed;
int status;
u32 status;
/* Wait for parent by reading from the pipe. Exit if read fails. */
@ -524,7 +527,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
volatile u8 *stop_soon_p, u8 debug_child_output) {
int st_pipe[2], ctl_pipe[2];
s32 status;
u32 status;
s32 rlen;
char *ignore_autodict = getenv("AFL_NO_AUTODICT");
@ -575,7 +578,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
void *nyx_config = fsrv->nyx_handlers->nyx_config_load(fsrv->target_path);
fsrv->nyx_handlers->nyx_config_set_workdir_path(nyx_config, workdir_path);
fsrv->nyx_handlers->nyx_config_set_input_buffer_size(nyx_config, MAX_FILE);
fsrv->nyx_handlers->nyx_config_set_input_buffer_size(nyx_config,
fsrv->max_length);
fsrv->nyx_handlers->nyx_config_set_input_buffer_write_protection(nyx_config,
true);
@ -724,7 +728,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
}
/* autodict in Nyx mode */
if (!ignore_autodict) {
if (!ignore_autodict && fsrv->add_extra_func) {
char *x =
alloc_printf("%s/workdir/dump/afl_autodict.txt", fsrv->out_dir_path);
@ -1017,15 +1021,210 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (rlen == 4) {
if (status >= 0x41464c00 && status <= 0x41464cff) {
/*
* The new fork server model works like this:
* Client: sends "AFLx" in little endian, with x being the forkserver
* protocol version.
* Server: replies with XOR of the message or exits with an error if it
* is not a supported version.
* Client: sends 32 bit of options and then sends all parameters of
* the options, one after another, increasing by option number.
* Ends with "AFLx".
* After the initial protocol version confirmation the server does not
* send any data anymore - except a future option requires this.
*/
FATAL(
"Target uses the new forkserver model, you need to switch to a newer "
"afl-fuzz too!");
if ((status & FS_NEW_ERROR) == FS_NEW_ERROR) {
report_error_and_exit(status & 0x0000ffff);
}
if (!be_quiet) { OKF("All right - fork server is up."); }
if (status >= 0x41464c00 && status <= 0x41464cff) {
u32 version = status - 0x41464c00;
if (!version) {
FATAL(
"Fork server version is not assigned, this should not happen. "
"Recompile target.");
} else if (version < FS_NEW_VERSION_MIN || version > FS_NEW_VERSION_MAX) {
FATAL(
"Fork server version is not not supported. Recompile the target.");
}
u32 keep = status;
status ^= 0xffffffff;
if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) {
FATAL("Writing to forkserver failed.");
}
if (!be_quiet) {
OKF("All right - new fork server model v%u is up.", version);
}
rlen = read(fsrv->fsrv_st_fd, &status, 4);
if (getenv("AFL_DEBUG")) {
ACTF("Forkserver options received: (0x%08x)", status);
}
if ((status & FS_NEW_OPT_MAPSIZE)) {
u32 tmp_map_size;
rlen = read(fsrv->fsrv_st_fd, &tmp_map_size, 4);
if (!fsrv->map_size) { fsrv->map_size = MAP_SIZE; }
fsrv->real_map_size = tmp_map_size;
if (tmp_map_size % 64) {
tmp_map_size = (((tmp_map_size + 63) >> 6) << 6);
}
if (!be_quiet) { ACTF("Target map size: %u", fsrv->real_map_size); }
if (tmp_map_size > fsrv->map_size) {
FATAL(
"Target's coverage map size of %u is larger than the one this "
"AFL++ is set with (%u). Either set AFL_MAP_SIZE=%u and "
"restart "
" afl-fuzz, or change MAP_SIZE_POW2 in config.h and recompile "
"afl-fuzz",
tmp_map_size, fsrv->map_size, tmp_map_size);
}
fsrv->map_size = tmp_map_size;
} else {
fsrv->real_map_size = fsrv->map_size = MAP_SIZE;
}
if (status & FS_NEW_OPT_SHDMEM_FUZZ) {
if (fsrv->support_shmem_fuzz) {
fsrv->use_shmem_fuzz = 1;
if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); }
} else {
FATAL(
"Target requested sharedmem fuzzing, but we failed to enable "
"it.");
}
}
if (status & FS_NEW_OPT_AUTODICT) {
// even if we do not need the dictionary we have to read it
u32 dict_size;
if (read(fsrv->fsrv_st_fd, &dict_size, 4) != 4) {
FATAL("Reading from forkserver failed.");
}
if (dict_size < 2 || dict_size > 0xffffff) {
FATAL("Dictionary has an illegal size: %d", dict_size);
}
u32 offset = 0, count = 0;
u8 *dict = ck_alloc(dict_size);
if (dict == NULL) {
FATAL("Could not allocate %u bytes of autodictionary memory",
dict_size);
}
while (offset < dict_size) {
rlen = read(fsrv->fsrv_st_fd, dict + offset, dict_size - offset);
if (rlen > 0) {
offset += rlen;
} else {
FATAL(
"Reading autodictionary fail at position %u with %u bytes "
"left.",
offset, dict_size - offset);
}
}
offset = 0;
while (offset < dict_size && (u8)dict[offset] + offset < dict_size) {
if (!ignore_autodict && fsrv->add_extra_func) {
fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1,
(u8)dict[offset]);
count++;
}
offset += (1 + dict[offset]);
}
if (!be_quiet && count) {
ACTF("Loaded %u autodictionary entries", count);
}
ck_free(dict);
}
u32 status2;
rlen = read(fsrv->fsrv_st_fd, &status2, 4);
if (status2 != keep) {
FATAL("Error in forkserver communication (%08x=>%08x)", keep, status2);
}
} else {
if (!fsrv->qemu_mode && !fsrv->cs_mode
#ifdef __linux__
&& !fsrv->nyx_mode
#endif
) {
WARNF(
"Old fork server model is used by the target, this still works "
"though.");
}
if (!be_quiet) { OKF("All right - old fork server is up."); }
if (getenv("AFL_DEBUG")) {
@ -1036,10 +1235,17 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if ((status & FS_OPT_ERROR) == FS_OPT_ERROR)
report_error_and_exit(FS_OPT_GET_ERROR(status));
if (fsrv->cmplog_binary && !fsrv->qemu_mode) {
FATAL("Target was compiled with outdated CMPLOG, recompile it!\n");
}
if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) {
// workaround for recent AFL++ versions
if ((status & FS_OPT_OLD_AFLPP_WORKAROUND) == FS_OPT_OLD_AFLPP_WORKAROUND)
if ((status & FS_OPT_OLD_AFLPP_WORKAROUND) ==
FS_OPT_OLD_AFLPP_WORKAROUND)
status = (status & 0xf0ffffff);
if ((status & FS_OPT_NEWCMPLOG) == 0 && fsrv->cmplog_binary) {
@ -1110,7 +1316,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
FATAL(
"Target's coverage map size of %u is larger than the one this "
"AFL++ is set with (%u). Either set AFL_MAP_SIZE=%u and restart "
"AFL++ is set with (%u). Either set AFL_MAP_SIZE=%u and "
"restart "
" afl-fuzz, or change MAP_SIZE_POW2 in config.h and recompile "
"afl-fuzz",
tmp_map_size, fsrv->map_size, tmp_map_size);
@ -1183,7 +1390,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
u8 *dict = ck_alloc(len);
if (dict == NULL) {
FATAL("Could not allocate %u bytes of autodictionary memory", len);
FATAL("Could not allocate %u bytes of autodictionary memory",
len);
}
@ -1226,6 +1434,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
}
}
return;
}
@ -1599,6 +1809,11 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
u32 exec_ms;
u32 write_value = fsrv->last_run_timed_out;
#ifdef AFL_PERSISTENT_RECORD
fsrv_run_result_t retval = FSRV_RUN_OK;
char *persistent_out_fmt;
#endif
#ifdef __linux__
if (fsrv->nyx_mode) {
@ -1628,6 +1843,8 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
case Timeout:
return FSRV_RUN_TMOUT;
case InvalidWriteToPayload:
if (!!getenv("AFL_NYX_HANDLE_INVALID_WRITE")) { return FSRV_RUN_CRASH; }
/* ??? */
FATAL("FixMe: Nyx InvalidWriteToPayload handler is missing");
break;
@ -1661,7 +1878,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
territory. */
#ifdef __linux__
if (!fsrv->nyx_mode) {
if (likely(!fsrv->nyx_mode)) {
memset(fsrv->trace_bits, 0, fsrv->map_size);
MEM_BARRIER();
@ -1731,7 +1948,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
if (exec_ms > timeout) {
/* If there was no response from forkserver after timeout seconds,
/* If there was no response from forkserver after timeout milliseconds,
we kill the child. The forkserver should inform us afterwards */
s32 tmp_pid = fsrv->child_pid;
@ -1798,6 +2015,18 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
if (unlikely(fsrv->last_run_timed_out)) {
fsrv->last_kill_signal = fsrv->child_kill_signal;
#ifdef AFL_PERSISTENT_RECORD
if (unlikely(fsrv->persistent_record)) {
retval = FSRV_RUN_TMOUT;
persistent_out_fmt = "%s/hangs/RECORD:%06u,cnt:%06u%s%s";
goto store_persistent_record;
}
#endif
return FSRV_RUN_TMOUT;
}
@ -1819,9 +2048,31 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
(fsrv->uses_crash_exitcode &&
WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode))) {
/* For a proper crash, set last_kill_signal to WTERMSIG, else set it to 0 */
fsrv->last_kill_signal =
WIFSIGNALED(fsrv->child_status) ? WTERMSIG(fsrv->child_status) : 0;
#ifdef AFL_PERSISTENT_RECORD
if (unlikely(fsrv->persistent_record)) {
retval = FSRV_RUN_CRASH;
persistent_out_fmt = "%s/crashes/RECORD:%06u,cnt:%06u%s%s";
goto store_persistent_record;
}
#endif
return FSRV_RUN_CRASH;
}
/* success :) */
return FSRV_RUN_OK;
#ifdef AFL_PERSISTENT_RECORD
store_persistent_record: {
char fn[PATH_MAX];
u32 i, writecnt = 0;
for (i = 0; i < fsrv->persistent_record; ++i) {
@ -1831,9 +2082,13 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
u32 len = fsrv->persistent_record_len[entry];
if (likely(len && data)) {
snprintf(fn, sizeof(fn), "%s/RECORD:%06u,cnt:%06u",
fsrv->persistent_record_dir, fsrv->persistent_record_cnt,
writecnt++);
snprintf(
fn, sizeof(fn), persistent_out_fmt, fsrv->persistent_record_dir,
fsrv->persistent_record_cnt, writecnt++,
((afl_state_t *)(fsrv->afl_ptr))->file_extension ? "." : "",
((afl_state_t *)(fsrv->afl_ptr))->file_extension
? (const char *)((afl_state_t *)(fsrv->afl_ptr))->file_extension
: "");
int fd = open(fn, O_CREAT | O_TRUNC | O_WRONLY, 0644);
if (fd >= 0) {
@ -1848,20 +2103,12 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
++fsrv->persistent_record_cnt;
return retval;
}
#endif
/* For a proper crash, set last_kill_signal to WTERMSIG, else set it to 0 */
fsrv->last_kill_signal =
WIFSIGNALED(fsrv->child_status) ? WTERMSIG(fsrv->child_status) : 0;
return FSRV_RUN_CRASH;
}
/* success :) */
return FSRV_RUN_OK;
}
void afl_fsrv_killall() {

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
@ -527,21 +527,41 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
#ifndef SIMPLE_FILES
queue_fn =
alloc_printf("%s/queue/id:%06u,%s", afl->out_dir, afl->queued_items,
if (!afl->afl_env.afl_sha1_filenames) {
queue_fn = alloc_printf(
"%s/queue/id:%06u,%s%s%s", afl->out_dir, afl->queued_items,
describe_op(afl, new_bits + is_timeout,
NAME_MAX - strlen("id:000000,")));
NAME_MAX - strlen("id:000000,")),
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
} else {
const char *hex = sha1_hex(mem, len);
queue_fn = alloc_printf(
"%s/queue/%s%s%s", afl->out_dir, hex, afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
ck_free((char *)hex);
}
#else
queue_fn =
alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_items);
queue_fn = alloc_printf(
"%s/queue/id_%06u", afl->out_dir, afl->queued_items,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
#endif /* ^!SIMPLE_FILES */
fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); }
fd = permissive_create(afl, queue_fn);
if (likely(fd >= 0)) {
ck_write(fd, mem, len, queue_fn);
close(fd);
}
add_to_queue(afl, queue_fn, len, 0);
if (unlikely(afl->fuzz_mode) &&
@ -739,14 +759,29 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
#ifndef SIMPLE_FILES
snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s", afl->out_dir,
if (!afl->afl_env.afl_sha1_filenames) {
snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s%s%s", afl->out_dir,
afl->saved_hangs,
describe_op(afl, 0, NAME_MAX - strlen("id:000000,")));
describe_op(afl, 0, NAME_MAX - strlen("id:000000,")),
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
} else {
const char *hex = sha1_hex(mem, len);
snprintf(fn, PATH_MAX, "%s/hangs/%s%s%s", afl->out_dir, hex,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
ck_free((char *)hex);
}
#else
snprintf(fn, PATH_MAX, "%s/hangs/id_%06llu", afl->out_dir,
afl->saved_hangs);
snprintf(fn, PATH_MAX, "%s/hangs/id_%06llu%s%s", afl->out_dir,
afl->saved_hangs, afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
#endif /* ^!SIMPLE_FILES */
@ -792,14 +827,30 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
#ifndef SIMPLE_FILES
snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir,
afl->saved_crashes, afl->fsrv.last_kill_signal,
describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")));
if (!afl->afl_env.afl_sha1_filenames) {
snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s",
afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal,
describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")),
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
} else {
const char *hex = sha1_hex(mem, len);
snprintf(fn, PATH_MAX, "%s/crashes/%s%s%s", afl->out_dir, hex,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
ck_free((char *)hex);
}
#else
snprintf(fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", afl->out_dir,
afl->saved_crashes, afl->fsrv.last_kill_signal);
snprintf(fn, PATH_MAX, "%s/crashes/id_%06llu_%02u%s%s", afl->out_dir,
afl->saved_crashes, afl->fsrv.last_kill_signal,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
#endif /* ^!SIMPLE_FILES */
@ -862,11 +913,14 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
/* If we're here, we apparently want to save the crash or hang
test case, too. */
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn); }
fd = permissive_create(afl, fn);
if (fd >= 0) {
ck_write(fd, mem, len, fn);
close(fd);
}
#ifdef __linux__
if (afl->fsrv.nyx_mode && fault == FSRV_RUN_CRASH) {

View File

@ -7,7 +7,7 @@
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
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
@ -742,8 +742,11 @@ void save_auto(afl_state_t *afl) {
for (i = 0; i < MIN((u32)USE_AUTO_EXTRAS, afl->a_extras_cnt); ++i) {
u8 *fn =
alloc_printf("%s/queue/.state/auto_extras/auto_%06u", afl->out_dir, i);
u8 *fn = alloc_printf(
"%s/queue/.state/auto_extras/auto_%06u%s%s", afl->out_dir, i,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
s32 fd;
fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION);

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
@ -459,6 +459,24 @@ void bind_to_free_cpu(afl_state_t *afl) {
#endif /* HAVE_AFFINITY */
/* transforms spaces in a string to underscores (inplace) */
static void no_spaces(u8 *string) {
if (string) {
u8 *ptr = string;
while (*ptr != 0) {
if (*ptr == ' ') { *ptr = '_'; }
++ptr;
}
}
}
/* Shuffle an array of pointers. Might be slightly biased. */
static void shuffle_ptrs(afl_state_t *afl, void **ptrs, u32 cnt) {
@ -559,6 +577,8 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
afl->stage_cur = 0;
afl->stage_max = 0;
show_stats(afl);
for (i = 0; i < (u32)nl_cnt; ++i) {
struct stat st;
@ -637,7 +657,12 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
munmap(mem, st.st_size);
close(fd);
if (st.st_mtime > mtime_max) mtime_max = st.st_mtime;
if (st.st_mtime > mtime_max) {
mtime_max = st.st_mtime;
show_stats(afl);
}
}
@ -914,6 +939,14 @@ void perform_dry_run(afl_state_t *afl) {
res = calibrate_case(afl, q, use_mem, 0, 1);
/* For AFLFast schedules we update the queue entry */
if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE) &&
likely(q->exec_cksum)) {
q->n_fuzz_entry = q->exec_cksum % N_FUZZ_SIZE;
}
if (afl->stop_soon) { return; }
if (res == afl->crash_mode || res == FSRV_RUN_NOBITS) {
@ -1157,18 +1190,35 @@ void perform_dry_run(afl_state_t *afl) {
#ifndef SIMPLE_FILES
snprintf(crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s",
if (!afl->afl_env.afl_sha1_filenames) {
snprintf(
crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s%s",
afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal,
describe_op(afl, 0,
NAME_MAX - strlen("id:000000,sig:00,") -
strlen(use_name)),
use_name);
describe_op(
afl, 0,
NAME_MAX - strlen("id:000000,sig:00,") - strlen(use_name)),
use_name, afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
} else {
const char *hex = sha1_hex(use_mem, read_len);
snprintf(
crash_fn, PATH_MAX, "%s/crashes/%s%s%s", afl->out_dir, hex,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
ck_free((char *)hex);
}
#else
snprintf(crash_fn, PATH_MAX, "%s/crashes/id_%06llu_%02u",
afl->out_dir, afl->saved_crashes,
afl->fsrv.last_kill_signal);
snprintf(
crash_fn, PATH_MAX, "%s/crashes/id_%06llu_%02u%s%s", afl->out_dir,
afl->saved_crashes, afl->fsrv.last_kill_signal,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
#endif
@ -1372,11 +1422,11 @@ void perform_dry_run(afl_state_t *afl) {
static void link_or_copy(u8 *old_path, u8 *new_path) {
s32 i = link(old_path, new_path);
if (!i) { return; }
s32 sfd, dfd;
u8 *tmp;
if (!i) { return; }
sfd = open(old_path, O_RDONLY);
if (sfd < 0) { PFATAL("Unable to open '%s'", old_path); }
@ -1439,7 +1489,9 @@ void pivot_inputs(afl_state_t *afl) {
u32 src_id;
afl->resuming_fuzz = 1;
nfn = alloc_printf("%s/queue/%s", afl->out_dir, rsl);
nfn = alloc_printf(
"%s/queue/%s%s%s", afl->out_dir, rsl, afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
/* Since we're at it, let's also get the parent and figure out the
appropriate depth for this entry. */
@ -1479,12 +1531,33 @@ void pivot_inputs(afl_state_t *afl) {
}
nfn = alloc_printf("%s/queue/id:%06u,time:0,execs:%llu,orig:%s",
afl->out_dir, id, afl->fsrv.total_execs, use_name);
if (!afl->afl_env.afl_sha1_filenames) {
nfn = alloc_printf(
"%s/queue/id:%06u,time:0,execs:%llu,orig:%s%s%s", afl->out_dir, id,
afl->fsrv.total_execs, use_name, afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
} else {
const char *hex = sha1_hex_for_file(q->fname, q->len);
nfn = alloc_printf(
"%s/queue/%s%s%s", afl->out_dir, hex,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
ck_free((char *)hex);
}
u8 *pos = strrchr(nfn, '/');
no_spaces(pos + 30);
#else
nfn = alloc_printf("%s/queue/id_%06u", afl->out_dir, id);
nfn = alloc_printf(
"%s/queue/id_%06u%s%s", afl->out_dir, id,
afl->file_extension ? "." : "",
afl->file_extension ? (const char *)afl->file_extension : "");
#endif /* ^!SIMPLE_FILES */
@ -1691,10 +1764,11 @@ double get_runnable_processes(void) {
void nuke_resume_dir(afl_state_t *afl) {
u8 *const case_prefix = afl->afl_env.afl_sha1_filenames ? "" : CASE_PREFIX;
u8 *fn;
fn = alloc_printf("%s/_resume/.state/deterministic_done", afl->out_dir);
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
ck_free(fn);
fn = alloc_printf("%s/_resume/.state/auto_extras", afl->out_dir);
@ -1702,11 +1776,11 @@ void nuke_resume_dir(afl_state_t *afl) {
ck_free(fn);
fn = alloc_printf("%s/_resume/.state/redundant_edges", afl->out_dir);
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
ck_free(fn);
fn = alloc_printf("%s/_resume/.state/variable_behavior", afl->out_dir);
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
ck_free(fn);
fn = alloc_printf("%s/_resume/.state", afl->out_dir);
@ -1714,7 +1788,7 @@ void nuke_resume_dir(afl_state_t *afl) {
ck_free(fn);
fn = alloc_printf("%s/_resume", afl->out_dir);
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
ck_free(fn);
return;
@ -1731,6 +1805,7 @@ dir_cleanup_failed:
static void handle_existing_out_dir(afl_state_t *afl) {
u8 *const case_prefix = afl->afl_env.afl_sha1_filenames ? "" : CASE_PREFIX;
FILE *f;
u8 *fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
@ -1854,7 +1929,7 @@ static void handle_existing_out_dir(afl_state_t *afl) {
/* Next, we need to clean up <afl->out_dir>/queue/.state/ subdirectories: */
fn = alloc_printf("%s/queue/.state/deterministic_done", afl->out_dir);
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
ck_free(fn);
fn = alloc_printf("%s/queue/.state/auto_extras", afl->out_dir);
@ -1862,11 +1937,11 @@ static void handle_existing_out_dir(afl_state_t *afl) {
ck_free(fn);
fn = alloc_printf("%s/queue/.state/redundant_edges", afl->out_dir);
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
ck_free(fn);
fn = alloc_printf("%s/queue/.state/variable_behavior", afl->out_dir);
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
ck_free(fn);
/* Then, get rid of the .state subdirectory itself (should be empty by now)
@ -1877,7 +1952,7 @@ static void handle_existing_out_dir(afl_state_t *afl) {
ck_free(fn);
fn = alloc_printf("%s/queue", afl->out_dir);
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
ck_free(fn);
/* All right, let's do <afl->out_dir>/crashes/id:* and
@ -1921,7 +1996,10 @@ static void handle_existing_out_dir(afl_state_t *afl) {
}
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
#ifdef AFL_PERSISTENT_RECORD
delete_files(fn, RECORD_PREFIX);
#endif
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
ck_free(fn);
fn = alloc_printf("%s/hangs", afl->out_dir);
@ -1953,7 +2031,10 @@ static void handle_existing_out_dir(afl_state_t *afl) {
}
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
#ifdef AFL_PERSISTENT_RECORD
delete_files(fn, RECORD_PREFIX);
#endif
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
ck_free(fn);
/* And now, for some finishing touches. */

View File

@ -5,7 +5,7 @@
Originally written by Shengtuo Hu
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Dominik Maier <mail@dmnk.co>

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
@ -26,6 +26,7 @@
#include <limits.h>
#include <ctype.h>
#include <math.h>
#include <xgboost/c_api.h>
#ifdef _STANDALONE_MODULE
void minimize_bits(afl_state_t *afl, u8 *dst, u8 *src) {
@ -117,7 +118,7 @@ void create_alias_table(afl_state_t *afl) {
double avg_exec_us = 0.0;
double avg_bitmap_size = 0.0;
double avg_top_size = 0.0;
double avg_len = 0.0;
u32 active = 0;
for (i = 0; i < n; i++) {
@ -128,8 +129,8 @@ void create_alias_table(afl_state_t *afl) {
if (likely(!q->disabled)) {
avg_exec_us += q->exec_us;
avg_bitmap_size += log(q->bitmap_size);
avg_top_size += q->tc_ref;
avg_bitmap_size += q->bitmap_size;
avg_len += q->len;
++active;
}
@ -138,7 +139,10 @@ void create_alias_table(afl_state_t *afl) {
avg_exec_us /= active;
avg_bitmap_size /= active;
avg_top_size /= active;
avg_len /= active;
float *table = malloc((active + 1) * 3 * sizeof(float));
float *pentry = table;
for (i = 0; i < n; i++) {
@ -146,29 +150,52 @@ void create_alias_table(afl_state_t *afl) {
if (likely(!q->disabled)) {
q->weight =
compute_weight(afl, q, avg_exec_us, avg_bitmap_size, avg_top_size);
*pentry++ = q->len / avg_len;
*pentry++ = q->exec_us / avg_exec_us;
*pentry++ = q->bitmap_size / avg_bitmap_size;
q->perf_score = calculate_score(afl, q);
sum += q->weight;
}
}
if (unlikely(afl->schedule == MMOPT) && afl->queued_discovered) {
DMatrixHandle dtest;
BoosterHandle booster;
u32 cnt = afl->queued_discovered >= 5 ? 5 : afl->queued_discovered;
// Erstellen einer DMatrix aus dem Array
XGDMatrixCreateFromMat((float *)table, 3, active, -1, &dtest);
XGBoosterCreate(&dtest, 1, &booster);
u8* model = NULL;//find_afl_binary("/out", "model.bin");
if (!model) model = find_afl_binary("./", "model.bin");
if (!model) FATAL("mode.bin not found!");
if (XGBoosterLoadModel(booster, "./model.bin"))
FATAL("model load failed!");
for (i = n - cnt; i < n; i++) {
bst_ulong out_len;
const float *predictions;
XGBoosterPredict(booster, dtest, 0, 0, 0, &out_len, &predictions);
// Ausgabe der Vorhersagen
int count = 0;
for (i = 0; i < n; i++) {
struct queue_entry *q = afl->queue_buf[i];
if (likely(!q->disabled)) { q->weight *= 2.0; }
if (likely(!q->disabled)) {
if (unlikely(afl->debug))
fprintf(stderr, "Prediction[%u] = %f\n", i, predictions[count]);
afl->queue_buf[i]->weight = predictions[count++];
sum += predictions[count++];
}
}
// Freigeben der Ressourcen
XGBoosterFree(booster);
XGDMatrixFree(dtest);
free(table);
for (i = 0; i < n; i++) {
// weight is always 0 for disabled entries
@ -370,9 +397,9 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
s32 fd;
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
close(fd);
if (unlikely(afl->afl_env.afl_disable_redundant)) { q->disabled = 1; }
fd = permissive_create(afl, fn);
if (fd >= 0) { close(fd); }
} else {
@ -1301,7 +1328,8 @@ inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) {
static u32 do_once = 0; // because even threaded we would want this. WIP
while (unlikely(
afl->q_testcase_cache_size + len >= afl->q_testcase_max_cache_size ||
(afl->q_testcase_cache_size + len >= afl->q_testcase_max_cache_size &&
afl->q_testcase_cache_count > 1) ||
afl->q_testcase_cache_count >= afl->q_testcase_max_cache_entries - 1)) {
/* We want a max number of entries to the cache that we learn.

View File

@ -7,11 +7,11 @@
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
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
Copyright 2019-2023 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.
@ -29,6 +29,7 @@
#include "cmplog.h"
// #define _DEBUG
// #define USE_HASHMAP
// #define CMPLOG_INTROSPECTION
// CMP attribute enum
@ -87,6 +88,13 @@ static u32 hshape;
static u64 screen_update;
static u64 last_update;
#ifdef USE_HASHMAP
// hashmap functions
void hashmap_reset();
bool hashmap_search_and_add(uint8_t type, uint64_t key);
bool hashmap_search_and_add_ptr(uint8_t type, u8 *key);
#endif
static struct range *add_range(struct range *ranges, u32 start, u32 end) {
struct range *r = ck_alloc_nozero(sizeof(struct range));
@ -795,7 +803,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
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];
// u8 *o_buf_8 = &orig_buf[idx];
u32 its_len = MIN(len - idx, taint_len);
@ -836,6 +844,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
// necessary for preventing heap access overflow
bytes = MIN(bytes, len - idx);
if (unlikely(bytes <= 1)) { return 0; }
// reverse atoi()/strnu?toll() is expensive, so we only to it in lvl 3
if (afl->cmplog_enable_transform && (lvl & LVL3)) {
@ -1266,6 +1275,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
/*
if (*status != 1) { // u8
// if (its_len >= 1)
@ -1290,6 +1300,8 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
}
*/
}
// If 'S' is set for cmplog mode then we try a scale encoding of the value.
@ -1881,6 +1893,8 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
hshape = SHAPE_BYTES(h->shape);
if (hshape < 2) { return 0; }
if (h->hits > CMP_MAP_H) {
loggeds = CMP_MAP_H;
@ -1906,8 +1920,6 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
#endif
if (hshape < 2) { return 0; }
for (i = 0; i < loggeds; ++i) {
struct cmp_operands *o = &afl->shm.cmp_map->log[key][i];
@ -1945,6 +1957,19 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
}
#ifdef USE_HASHMAP
// TODO: add attribute? not sure
if (hshape <= 8 && hashmap_search_and_add(hshape - 1, o->v0) &&
hashmap_search_and_add(hshape - 1, orig_o->v0) &&
hashmap_search_and_add(hshape - 1, o->v1) &&
hashmap_search_and_add(hshape - 1, orig_o->v1)) {
continue;
}
#endif
#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, hshape);
@ -2219,15 +2244,15 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
}
if (l0 == 0 || l1 == 0 || ol0 == 0 || ol1 == 0 || l0 > 31 || l1 > 31 ||
ol0 > 31 || ol1 > 31) {
if (l0 == 0 || l1 == 0 || ol0 == 0 || ol1 == 0 || l0 > 32 || l1 > 32 ||
ol0 > 32 || ol1 > 32) {
l0 = ol0 = hshape;
}
u8 lmax = MAX(l0, ol0);
u8 save[40];
u8 save[80];
u32 saved_idx = idx, pre, from = 0, to = 0, i, j;
u32 its_len = MIN(MIN(lmax, hshape), len - idx);
its_len = MIN(its_len, taint_len);
@ -2330,7 +2355,7 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
u32 tob64 = 0, fromb64 = 0;
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];
u8 xor_val[64], arith_val[64], tmp[64];
idx = saved_idx;
its_len = saved_its_len;
@ -2615,12 +2640,13 @@ static u8 rtn_extend_encoding(afl_state_t *afl, u8 entry,
}
memcpy(buf + idx, tmp, hlen + 1 + off);
u32 tmp_l = hlen + 1 + off;
memcpy(buf + idx, tmp, tmp_l);
if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; }
tmp[hlen + 1 + off] = 0;
tmp[tmp_l] = 0;
// fprintf(stderr, "RTN ATTEMPT idx=%u len=%u fromhex %u %s %s result
// %u\n", idx, len, fromhex, tmp, repl, *status);
memcpy(buf + idx, save, hlen + 1 + off);
memcpy(buf + idx, save, tmp_l);
}
@ -2738,15 +2764,15 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
#ifdef _DEBUG
u32 j;
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,
hshape, h->attribute);
fprintf(stderr, "RTN N hits=%u shape=%u attr=%u v0=", h->hits, hshape,
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, hshape, hh->attribute);
fprintf(stderr, "\nRTN O hits=%u shape=%u attr=%u o0=", hh->hits, hshape,
hh->attribute);
for (j = 0; j < 8; j++)
fprintf(stderr, "%02x", orig_o->v0[j]);
fprintf(stderr, " o1=");
@ -2755,6 +2781,18 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
fprintf(stderr, "\n");
#endif
#ifdef USE_HASHMAP
if (hshape <= 8 && hashmap_search_and_add_ptr(hshape - 1, o->v0) &&
hashmap_search_and_add_ptr(hshape - 1, orig_o->v0) &&
hashmap_search_and_add_ptr(hshape - 1, o->v1) &&
hashmap_search_and_add_ptr(hshape - 1, orig_o->v1)) {
continue;
}
#endif
t = taint;
while (t->next) {
@ -3021,6 +3059,10 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
// Start insertion loop
#ifdef USE_HASHMAP
hashmap_reset();
#endif
u64 orig_hit_cnt, new_hit_cnt;
u64 orig_execs = afl->fsrv.total_execs;
orig_hit_cnt = afl->queued_items + afl->saved_crashes;

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com> and
Dominik Maier <mail@dmnk.co>
@ -409,6 +409,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
u32 use_tmout = afl->fsrv.exec_tmout;
u8 *old_sn = afl->stage_name;
u64 calibration_start_us = get_cur_time_us();
if (unlikely(afl->shm.cmplog_mode)) { q->exec_cksum = 0; }
/* Be a bit more generous about timeouts when resuming sessions, or when
@ -504,6 +505,10 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
fault = fuzz_run_target(afl, &afl->fsrv, use_tmout);
// update the time spend in calibration after each execution, as those may
// be slow
update_calibration_time(afl, &calibration_start_us);
/* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed,
we want to bail out quickly. */
@ -601,6 +606,8 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
}
q->exec_us = diff_us / afl->stage_max;
if (unlikely(!q->exec_us)) { q->exec_us = 1; }
q->bitmap_size = count_bytes(afl, afl->fsrv.trace_bits);
q->handicap = handicap;
q->cal_failed = 0;
@ -650,6 +657,7 @@ abort_calibration:
if (!first_run) { show_stats(afl); }
update_calibration_time(afl, &calibration_start_us);
return fault;
}
@ -669,11 +677,16 @@ void sync_fuzzers(afl_state_t *afl) {
afl->stage_max = afl->stage_cur = 0;
afl->cur_depth = 0;
u64 sync_start_us = get_cur_time_us();
/* Look at the entries created for every other fuzzer in the sync directory.
*/
while ((sd_ent = readdir(sd))) {
// since sync can take substantial amounts of time, update time spend every
// iteration
update_sync_time(afl, &sync_start_us);
u8 qd_synced_path[PATH_MAX], qd_path[PATH_MAX];
u32 min_accept = 0, next_min_accept = 0;
@ -760,6 +773,8 @@ void sync_fuzzers(afl_state_t *afl) {
afl->stage_cur = 0;
afl->stage_max = 0;
show_stats(afl);
/* For every file queued by this fuzzer, parse ID and see if we have
looked at it before; exec a test case if not. */
@ -811,15 +826,15 @@ void sync_fuzzers(afl_state_t *afl) {
/* See what happens. We rely on save_if_interesting() to catch major
errors and save the test case. */
(void)write_to_testcase(afl, (void **)&mem, st.st_size, 1);
u32 new_len = write_to_testcase(afl, (void **)&mem, st.st_size, 1);
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
if (afl->stop_soon) { goto close_sync; }
afl->syncing_party = sd_ent->d_name;
afl->queued_imported +=
save_if_interesting(afl, mem, st.st_size, fault);
afl->queued_imported += save_if_interesting(afl, mem, new_len, fault);
show_stats(afl);
afl->syncing_party = 0;
munmap(mem, st.st_size);
@ -861,6 +876,9 @@ void sync_fuzzers(afl_state_t *afl) {
if (afl->foreign_sync_cnt) read_foreign_testcases(afl, 0);
// add time in sync one last time
update_sync_time(afl, &sync_start_us);
afl->last_sync_time = get_cur_time();
afl->last_sync_cycle = afl->queue_cycle;
@ -872,8 +890,9 @@ void sync_fuzzers(afl_state_t *afl) {
u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
u8 needs_write = 0, fault = 0;
u32 orig_len = q->len;
u64 trim_start_us = get_cur_time_us();
/* Custom mutator trimmer */
if (afl->custom_mutators_count) {
@ -897,11 +916,15 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
}
if (custom_trimmed) return trimmed_case;
if (custom_trimmed) {
fault = trimmed_case;
goto abort_trimming;
}
}
u8 needs_write = 0, fault = 0;
u32 trim_exec = 0;
u32 remove_len;
u32 len_p2;
@ -912,7 +935,12 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
detected, it will still work to some extent, so we don't check for
this. */
if (unlikely(q->len < 5)) { return 0; }
if (unlikely(q->len < 5)) {
fault = 0;
goto abort_trimming;
}
afl->stage_name = afl->stage_name_buf;
afl->bytes_trim_in += q->len;
@ -946,6 +974,8 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
update_trim_time(afl, &trim_start_us);
if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; }
/* Note that we don't keep track of crashes or hangs here; maybe TODO?
@ -972,7 +1002,6 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
/* Let's save a clean trace, which will be needed by
update_bitmap_score once we're done with the trimming stuff. */
if (!needs_write) {
needs_write = 1;
@ -987,7 +1016,6 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
}
/* Since this can be slow, update the screen every now and then. */
if (!(trim_exec++ % afl->stats_update_freq)) { show_stats(afl); }
++afl->stage_cur;
@ -1002,6 +1030,68 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
if (needs_write) {
// run afl_custom_post_process
if (unlikely(afl->custom_mutators_count) &&
likely(!afl->afl_env.afl_post_process_keep_original)) {
ssize_t new_size = q->len;
u8 *new_mem = in_buf;
u8 *new_buf = NULL;
LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
if (el->afl_custom_post_process) {
new_size = el->afl_custom_post_process(el->data, new_mem, new_size,
&new_buf);
if (unlikely(!new_buf || new_size <= 0)) {
new_size = 0;
new_buf = new_mem;
} else {
new_mem = new_buf;
}
}
});
if (unlikely(!new_size)) {
new_size = q->len;
new_mem = in_buf;
}
if (unlikely(new_size < afl->min_length)) {
new_size = afl->min_length;
} else if (unlikely(new_size > afl->max_length)) {
new_size = afl->max_length;
}
q->len = new_size;
if (new_mem != in_buf && new_mem != NULL) {
new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), new_size);
if (unlikely(!new_buf)) { PFATAL("alloc"); }
memcpy(new_buf, new_mem, new_size);
in_buf = new_buf;
}
}
s32 fd;
if (unlikely(afl->no_unlink)) {
@ -1039,8 +1129,9 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
}
abort_trimming:
afl->bytes_trim_out += q->len;
update_trim_time(afl, &trim_start_us);
return fault;
}

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
@ -28,10 +28,6 @@
#include "afl-fuzz.h"
#include "envs.h"
s8 interesting_8[] = {INTERESTING_8};
s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
char *power_names[POWER_SCHEDULES_NUM] = {"explore", "mmopt", "exploit",
"fast", "coe", "lin",
"quad", "rare", "seek"};
@ -102,7 +98,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) {
afl->stats_update_freq = 1;
afl->stats_file_update_freq_msecs = STATS_UPDATE_SEC * 1000;
afl->stats_avg_exec = 0;
afl->skip_deterministic = 1;
afl->skip_deterministic = 0;
afl->sync_time = SYNC_TIME;
afl->cmplog_lvl = 2;
afl->min_length = 1;
@ -297,6 +293,16 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_cmplog_only_new =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
} else if (!strncmp(env, "AFL_DISABLE_REDUNDANT",
afl_environment_variable_len) ||
!strncmp(env, "AFL_NO_REDUNDANT",
afl_environment_variable_len)) {
afl->afl_env.afl_disable_redundant =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
} else if (!strncmp(env, "AFL_NO_STARTUP_CALIBRATION",
afl_environment_variable_len)) {
@ -623,6 +629,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
}
} else if (!strncmp(env, "AFL_SHA1_FILENAMES",
afl_environment_variable_len)) {
afl->afl_env.afl_sha1_filenames =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
}
} else {

View File

@ -5,8 +5,9 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Dominik Meier <mail@dmnk.co>,
Andrea Fioraldi <andreafioraldi@gmail.com>, and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>
Copyright 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
@ -133,6 +134,12 @@ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) {
}
static bool starts_with(char *key, char *line) {
return strncmp(key, line, strlen(key)) == 0;
}
/* load some of the existing stats file when resuming.*/
void load_stats_file(afl_state_t *afl) {
@ -175,23 +182,44 @@ void load_stats_file(afl_state_t *afl) {
strcpy(keystring, lstartptr);
lptr++;
char *nptr;
switch (lineno) {
if (starts_with("run_time", keystring)) {
case 3:
if (!strcmp(keystring, "run_time "))
afl->prev_run_time = 1000 * strtoull(lptr, &nptr, 10);
break;
case 5:
if (!strcmp(keystring, "cycles_done "))
}
if (starts_with("cycles_done", keystring)) {
afl->queue_cycle =
strtoull(lptr, &nptr, 10) ? strtoull(lptr, &nptr, 10) + 1 : 0;
break;
case 7:
if (!strcmp(keystring, "execs_done "))
}
if (starts_with("calibration_time", keystring)) {
afl->calibration_time_us = strtoull(lptr, &nptr, 10) * 1000000;
}
if (starts_with("sync_time", keystring)) {
afl->sync_time_us = strtoull(lptr, &nptr, 10) * 1000000;
}
if (starts_with("trim_time", keystring)) {
afl->trim_time_us = strtoull(lptr, &nptr, 10) * 1000000;
}
if (starts_with("execs_done", keystring)) {
afl->fsrv.total_execs = strtoull(lptr, &nptr, 10);
break;
case 10:
if (!strcmp(keystring, "corpus_count ")) {
}
if (starts_with("corpus_count", keystring)) {
u32 corpus_count = strtoul(lptr, &nptr, 10);
if (corpus_count != afl->queued_items) {
@ -199,34 +227,39 @@ void load_stats_file(afl_state_t *afl) {
WARNF(
"queue/ has been modified -- things might not work, you're "
"on your own!");
sleep(3);
}
}
break;
case 12:
if (!strcmp(keystring, "corpus_found "))
if (starts_with("corpus_found", keystring)) {
afl->queued_discovered = strtoul(lptr, &nptr, 10);
break;
case 13:
if (!strcmp(keystring, "corpus_imported "))
}
if (starts_with("corpus_imported", keystring)) {
afl->queued_imported = strtoul(lptr, &nptr, 10);
break;
case 14:
if (!strcmp(keystring, "max_depth "))
}
if (starts_with("max_depth", keystring)) {
afl->max_depth = strtoul(lptr, &nptr, 10);
break;
case 21:
if (!strcmp(keystring, "saved_crashes "))
}
if (starts_with("saved_crashes", keystring)) {
afl->saved_crashes = strtoull(lptr, &nptr, 10);
break;
case 22:
if (!strcmp(keystring, "saved_hangs "))
}
if (starts_with("saved_hangs", keystring)) {
afl->saved_hangs = strtoull(lptr, &nptr, 10);
break;
default:
break;
}
@ -288,8 +321,10 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
#ifndef __HAIKU__
if (getrusage(RUSAGE_CHILDREN, &rus)) { rus.ru_maxrss = 0; }
#endif
u64 runtime = afl->prev_run_time + cur_time - afl->start_time;
if (!runtime) { runtime = 1; }
u64 runtime_ms = afl->prev_run_time + cur_time - afl->start_time;
u64 overhead_ms =
(afl->calibration_time_us + afl->sync_time_us + afl->trim_time_us) / 1000;
if (!runtime_ms) { runtime_ms = 1; }
fprintf(
f,
@ -300,6 +335,10 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
"cycles_done : %llu\n"
"cycles_wo_finds : %llu\n"
"time_wo_finds : %llu\n"
"fuzz_time : %llu\n"
"calibration_time : %llu\n"
"sync_time : %llu\n"
"trim_time : %llu\n"
"execs_done : %llu\n"
"execs_per_sec : %0.02f\n"
"execs_ps_last_min : %0.02f\n"
@ -337,15 +376,18 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
"\n"
"target_mode : %s%s%s%s%s%s%s%s%s%s\n"
"command_line : %s\n",
(afl->start_time - afl->prev_run_time) / 1000, cur_time / 1000,
runtime / 1000, (u32)getpid(),
(afl->start_time /*- afl->prev_run_time*/) / 1000, cur_time / 1000,
runtime_ms / 1000, (u32)getpid(),
afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds,
afl->longest_find_time > cur_time - afl->last_find_time
? afl->longest_find_time / 1000
: ((afl->start_time == 0 || afl->last_find_time == 0)
? 0
: (cur_time - afl->last_find_time) / 1000),
afl->fsrv.total_execs, afl->fsrv.total_execs / ((double)(runtime) / 1000),
(runtime_ms - MIN(runtime_ms, overhead_ms)) / 1000,
afl->calibration_time_us / 1000000, afl->sync_time_us / 1000000,
afl->trim_time_us / 1000000, afl->fsrv.total_execs,
afl->fsrv.total_execs / ((double)(runtime_ms) / 1000),
afl->last_avg_execs_saved, afl->queued_items, afl->queued_favored,
afl->queued_discovered, afl->queued_imported, afl->queued_variable,
afl->max_depth, afl->current_entry, afl->pending_favored,
@ -589,9 +631,10 @@ void show_stats_normal(afl_state_t *afl) {
cur_ms = get_cur_time();
if (afl->most_time_key) {
if (afl->most_time_key && afl->queue_cycle) {
if (afl->most_time * 1000 < cur_ms - afl->start_time) {
if (afl->most_time * 1000 + afl->sync_time_us / 1000 <
cur_ms - afl->start_time) {
afl->most_time_key = 2;
afl->stop_soon = 2;
@ -600,7 +643,7 @@ void show_stats_normal(afl_state_t *afl) {
}
if (afl->most_execs_key == 1) {
if (afl->most_execs_key == 1 && afl->queue_cycle) {
if (afl->most_execs <= afl->fsrv.total_execs) {
@ -876,6 +919,10 @@ void show_stats_normal(afl_state_t *afl) {
#endif
if (banner_pad)
for (u32 i = 0; i < banner_pad; ++i)
strcat(banner, " ");
}
SAYF("\n%s\n", banner);
@ -1112,7 +1159,7 @@ void show_stats_normal(afl_state_t *afl) {
} else if (likely(afl->skip_deterministic)) {
strcpy(tmp, "disabled (default, enable with -D)");
strcpy(tmp, "disabled (-z switch used)");
} else {
@ -1284,7 +1331,9 @@ void show_stats_normal(afl_state_t *afl) {
sprintf(tmp, "disabled, ");
} else if (unlikely(!afl->bytes_trim_out)) {
} else if (unlikely(!afl->bytes_trim_out ||
afl->bytes_trim_in <= afl->bytes_trim_out)) {
sprintf(tmp, "n/a, ");
@ -1301,7 +1350,9 @@ void show_stats_normal(afl_state_t *afl) {
strcat(tmp, "disabled");
} else if (unlikely(!afl->blocks_eff_total)) {
} else if (unlikely(!afl->blocks_eff_total ||
afl->blocks_eff_select >= afl->blocks_eff_total)) {
strcat(tmp, "n/a");
@ -1415,9 +1466,10 @@ void show_stats_pizza(afl_state_t *afl) {
cur_ms = get_cur_time();
if (afl->most_time_key) {
if (afl->most_time_key && afl->queue_cycle) {
if (afl->most_time * 1000 < cur_ms - afl->start_time) {
if (afl->most_time * 1000 + afl->sync_time_us / 1000 <
cur_ms - afl->start_time) {
afl->most_time_key = 2;
afl->stop_soon = 2;
@ -1426,7 +1478,7 @@ void show_stats_pizza(afl_state_t *afl) {
}
if (afl->most_execs_key == 1) {
if (afl->most_execs_key == 1 && afl->queue_cycle) {
if (afl->most_execs <= afl->fsrv.total_execs) {
@ -2435,3 +2487,27 @@ void show_init_stats(afl_state_t *afl) {
}
void update_calibration_time(afl_state_t *afl, u64 *time) {
u64 cur = get_cur_time_us();
afl->calibration_time_us += cur - *time;
*time = cur;
}
void update_trim_time(afl_state_t *afl, u64 *time) {
u64 cur = get_cur_time_us();
afl->trim_time_us += cur - *time;
*time = cur;
}
void update_sync_time(afl_state_t *afl, u64 *time) {
u64 cur = get_cur_time_us();
afl->sync_time_us += cur - *time;
*time = cur;
}

View File

@ -5,8 +5,9 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Dominik Meier <mail@dmnk.co>,
Andrea Fioraldi <andreafioraldi@gmail.com>, and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>
Copyright 2016, 2017 Google Inc. All rights reserved.
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
@ -170,7 +171,6 @@ static void usage(u8 *argv0, int more_help) {
" -g minlength - set min length of generated fuzz input (default: 1)\n"
" -G maxlength - set max length of generated fuzz input (default: "
"%lu)\n"
" -D - enable (a new) effective deterministic fuzzing\n"
" -L minutes - use MOpt(imize) mode and set the time limit for "
"entering the\n"
" pacemaker mode (minutes of no new finds). 0 = "
@ -200,7 +200,8 @@ static void usage(u8 *argv0, int more_help) {
"Test settings:\n"
" -s seed - use a fixed seed for the RNG\n"
" -V seconds - fuzz for a specified time then terminate\n"
" -V seconds - fuzz for a specified time then terminate (fuzz time "
"only!)\n"
" -E execs - fuzz for an approx. no. of total executions then "
"terminate\n"
" Note: not precise and can have several more "
@ -213,7 +214,8 @@ static void usage(u8 *argv0, int more_help) {
" -F path - sync to a foreign fuzzer queue directory (requires "
"-M, can\n"
" be specified up to %u times)\n"
// " -d - skip deterministic fuzzing in -M mode\n"
" -z - skip the enhanced deterministic fuzzing\n"
" (note that the old -d and -D flags are ignored.)\n"
" -T text - text banner to show on the screen\n"
" -I command - execute this command/script when a new crash is "
"found\n"
@ -262,6 +264,7 @@ static void usage(u8 *argv0, int more_help) {
"AFL_CYCLE_SCHEDULES: after completing a cycle, switch to a different -p schedule\n"
"AFL_DEBUG: extra debugging output for Python mode trimming\n"
"AFL_DEBUG_CHILD: do not suppress stdout/stderr from target\n"
"AFL_DISABLE_REDUNDANT: disable any queue item that is redundant\n"
"AFL_DISABLE_TRIM: disable the trimming of test cases\n"
"AFL_DUMB_FORKSRV: use fork server without feedback from target\n"
"AFL_EXIT_WHEN_DONE: exit when all inputs are run and no new finds are found\n"
@ -401,6 +404,12 @@ static void usage(u8 *argv0, int more_help) {
SAYF("Compiled with _AFL_DOCUMENT_MUTATIONS.\n");
#endif
#ifdef _AFL_SPECIAL_PERFORMANCE
SAYF(
"Compiled with special performance options for this specific system, it "
"might not work on other platforms!\n");
#endif
SAYF("For additional help please consult %s/README.md :)\n\n", doc_path);
exit(1);
@ -539,7 +548,7 @@ int main(int argc, char **argv_orig, char **envp) {
// still available: HjJkKqruvwz
while ((opt = getopt(argc, argv,
"+a:Ab:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:"
"T:UV:WXx:YZ")) > 0) {
"T:UV:WXx:YzZ")) > 0) {
switch (opt) {
@ -955,20 +964,17 @@ int main(int argc, char **argv_orig, char **envp) {
break;
case 'D': /* partial deterministic */
case 'd':
case 'D': /* old deterministic */
afl->skip_deterministic = 0;
WARNF(
"Parameters -d and -D are deprecated, a new enhanced deterministic "
"fuzzing is active by default, to disable it use -z");
break;
case 'd': /* no deterministic */
case 'z': /* no deterministic */
// this is the default and currently a lot of infrastructure enforces
// it (e.g. clusterfuzz, fuzzbench) based on that this feature
// originally was bad performance wise. We now have a better
// implementation, hence if it is activated, we do not want to
// deactivate it by such setups.
// afl->skip_deterministic = 1;
afl->skip_deterministic = 1;
break;
case 'B': /* load bitmap */
@ -1232,6 +1238,7 @@ int main(int argc, char **argv_orig, char **envp) {
}
afl->old_seed_selection = 1;
u64 limit_time_puppet2 = afl->limit_time_puppet * 60 * 1000;
if ((s32)limit_time_puppet2 < afl->limit_time_puppet) {
@ -1558,7 +1565,11 @@ int main(int argc, char **argv_orig, char **envp) {
setenv("__AFL_OUT_DIR", afl->out_dir, 1);
if (get_afl_env("AFL_DISABLE_TRIM")) { afl->disable_trim = 1; }
if (get_afl_env("AFL_DISABLE_TRIM") || get_afl_env("AFL_NO_TRIM")) {
afl->disable_trim = 1;
}
if (getenv("AFL_NO_UI") && getenv("AFL_FORCE_UI")) {
@ -1794,6 +1805,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl_realloc(AFL_BUF_PARAM(ex), min_alloc);
afl->fsrv.use_fauxsrv = afl->non_instrumented_mode == 1 || afl->no_forkserver;
afl->fsrv.max_length = afl->max_length;
#ifdef __linux__
if (!afl->fsrv.nyx_mode) {
@ -2069,6 +2081,17 @@ int main(int argc, char **argv_orig, char **envp) {
}
/* Simply code if AFL_TMPDIR is used or not */
if (!afl->afl_env.afl_tmpdir) {
afl->tmp_dir = afl->out_dir;
} else {
afl->tmp_dir = afl->afl_env.afl_tmpdir;
}
write_setup_file(afl, argc, argv);
setup_cmdline_file(afl, argv + optind);
@ -2081,8 +2104,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (!afl->timeout_given) { find_timeout(afl); } // only for resumes!
if ((afl->tmp_dir = afl->afl_env.afl_tmpdir) != NULL &&
!afl->in_place_resume) {
if (afl->afl_env.afl_tmpdir && !afl->in_place_resume) {
char tmpfile[PATH_MAX];
@ -2107,10 +2129,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
} else {
afl->tmp_dir = afl->out_dir;
}
/* If we don't have a file name chosen yet, use a safe default. */
@ -2182,7 +2200,7 @@ int main(int argc, char **argv_orig, char **envp) {
}
afl->fsrv.persistent_record_dir = alloc_printf("%s/crashes", afl->out_dir);
afl->fsrv.persistent_record_dir = alloc_printf("%s", afl->out_dir);
}
@ -2489,8 +2507,15 @@ int main(int argc, char **argv_orig, char **envp) {
for (entry = 0; entry < afl->queued_items; ++entry)
if (!afl->queue_buf[entry]->disabled)
if (afl->queue_buf[entry]->exec_us > max_ms)
max_ms = afl->queue_buf[entry]->exec_us;
if ((afl->queue_buf[entry]->exec_us / 1000) > max_ms)
max_ms = afl->queue_buf[entry]->exec_us / 1000;
// Add 20% as a safety margin, capped to exec_tmout given in -t option
max_ms *= 1.2;
if (max_ms > afl->fsrv.exec_tmout) max_ms = afl->fsrv.exec_tmout;
// Ensure that there is a sensible timeout even for very fast binaries
if (max_ms < 5) max_ms = 5;
afl->fsrv.exec_tmout = max_ms;
afl->timeout_given = 1;
@ -2526,8 +2551,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
// (void)nice(-20); // does not improve the speed
// real start time, we reset, so this works correctly with -V
afl->start_time = get_cur_time();
#ifdef INTROSPECTION
u32 prev_saved_crashes = 0, prev_saved_tmouts = 0;
@ -2548,6 +2571,9 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("Writing mutation introspection to '%s'", ifn);
#endif
// real start time, we reset, so this works correctly with -V
afl->start_time = get_cur_time();
while (likely(!afl->stop_soon)) {
cull_queue(afl);
@ -3057,7 +3083,7 @@ stop_fuzzing:
afl_fsrv_deinit(&afl->fsrv);
/* remove tmpfile */
if (afl->tmp_dir != NULL && !afl->in_place_resume && afl->fsrv.out_file) {
if (!afl->in_place_resume && afl->fsrv.out_file) {
(void)unlink(afl->fsrv.out_file);

View File

@ -5,7 +5,7 @@
Originally written by Michal Zalewski
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.

View File

@ -5,7 +5,7 @@
Written by Marc Heuse <mh@mh-sec.de> for AFL++
Maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>
Andrea Fioraldi <andreafioraldi@gmail.com>
Dominik Maier <domenukk@gmail.com>

View File

@ -2,9 +2,17 @@
#include "afl-fuzz.h"
#include "types.h"
#ifdef _HAVE_AVX2
#define T1HA0_AESNI_AVAILABLE 1
#define T1HA_USE_FAST_ONESHOT_READ 1
#define T1HA_USE_INDIRECT_FUNCTIONS 1
#define T1HA_IA32AES_NAME XXH3_64bits
#include "t1ha0_ia32aes_b.h"
#else
#define XXH_INLINE_ALL
#include "xxhash.h"
#undef XXH_INLINE_ALL
#endif
void rand_set_seed(afl_state_t *afl, s64 init_seed) {
@ -87,3 +95,313 @@ inline u64 hash64(u8 *key, u32 len, u64 seed) {
}
// Public domain SHA1 implementation copied from:
// https://github.com/x42/liboauth/blob/7001b8256cd654952ec2515b055d2c5b243be600/src/sha1.c
/* This code is public-domain - it is based on libcrypt
* placed in the public domain by Wei Dai and other contributors.
*/
// gcc -Wall -DSHA1TEST -o sha1test sha1.c && ./sha1test
#include <stdint.h>
#include <string.h>
#ifdef __BIG_ENDIAN__
#define SHA_BIG_ENDIAN
#elif defined __LITTLE_ENDIAN__
/* override */
#elif defined __BYTE_ORDER
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define SHA_BIG_ENDIAN
#endif
#else // ! defined __LITTLE_ENDIAN__
#include <endian.h> // machine/endian.h
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define SHA_BIG_ENDIAN
#endif
#endif
/* header */
#define HASH_LENGTH 20
#define BLOCK_LENGTH 64
typedef struct sha1nfo {
uint32_t buffer[BLOCK_LENGTH / 4];
uint32_t state[HASH_LENGTH / 4];
uint32_t byteCount;
uint8_t bufferOffset;
uint8_t keyBuffer[BLOCK_LENGTH];
uint8_t innerHash[HASH_LENGTH];
} sha1nfo;
/* public API - prototypes - TODO: doxygen*/
/**
*/
void sha1_init(sha1nfo *s);
/**
*/
void sha1_writebyte(sha1nfo *s, uint8_t data);
/**
*/
void sha1_write(sha1nfo *s, const char *data, size_t len);
/**
*/
uint8_t *sha1_result(sha1nfo *s);
/**
*/
void sha1_initHmac(sha1nfo *s, const uint8_t *key, int keyLength);
/**
*/
uint8_t *sha1_resultHmac(sha1nfo *s);
/* code */
#define SHA1_K0 0x5a827999
#define SHA1_K20 0x6ed9eba1
#define SHA1_K40 0x8f1bbcdc
#define SHA1_K60 0xca62c1d6
void sha1_init(sha1nfo *s) {
s->state[0] = 0x67452301;
s->state[1] = 0xefcdab89;
s->state[2] = 0x98badcfe;
s->state[3] = 0x10325476;
s->state[4] = 0xc3d2e1f0;
s->byteCount = 0;
s->bufferOffset = 0;
}
uint32_t sha1_rol32(uint32_t number, uint8_t bits) {
return ((number << bits) | (number >> (32 - bits)));
}
void sha1_hashBlock(sha1nfo *s) {
uint8_t i;
uint32_t a, b, c, d, e, t;
a = s->state[0];
b = s->state[1];
c = s->state[2];
d = s->state[3];
e = s->state[4];
for (i = 0; i < 80; i++) {
if (i >= 16) {
t = s->buffer[(i + 13) & 15] ^ s->buffer[(i + 8) & 15] ^
s->buffer[(i + 2) & 15] ^ s->buffer[i & 15];
s->buffer[i & 15] = sha1_rol32(t, 1);
}
if (i < 20) {
t = (d ^ (b & (c ^ d))) + SHA1_K0;
} else if (i < 40) {
t = (b ^ c ^ d) + SHA1_K20;
} else if (i < 60) {
t = ((b & c) | (d & (b | c))) + SHA1_K40;
} else {
t = (b ^ c ^ d) + SHA1_K60;
}
t += sha1_rol32(a, 5) + e + s->buffer[i & 15];
e = d;
d = c;
c = sha1_rol32(b, 30);
b = a;
a = t;
}
s->state[0] += a;
s->state[1] += b;
s->state[2] += c;
s->state[3] += d;
s->state[4] += e;
}
void sha1_addUncounted(sha1nfo *s, uint8_t data) {
uint8_t *const b = (uint8_t *)s->buffer;
#ifdef SHA_BIG_ENDIAN
b[s->bufferOffset] = data;
#else
b[s->bufferOffset ^ 3] = data;
#endif
s->bufferOffset++;
if (s->bufferOffset == BLOCK_LENGTH) {
sha1_hashBlock(s);
s->bufferOffset = 0;
}
}
void sha1_writebyte(sha1nfo *s, uint8_t data) {
++s->byteCount;
sha1_addUncounted(s, data);
}
void sha1_write(sha1nfo *s, const char *data, size_t len) {
for (; len--;)
sha1_writebyte(s, (uint8_t)*data++);
}
void sha1_pad(sha1nfo *s) {
// Implement SHA-1 padding (fips180-2 §5.1.1)
// Pad with 0x80 followed by 0x00 until the end of the block
sha1_addUncounted(s, 0x80);
while (s->bufferOffset != 56)
sha1_addUncounted(s, 0x00);
// Append length in the last 8 bytes
sha1_addUncounted(s, 0); // We're only using 32 bit lengths
sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths
sha1_addUncounted(s, 0); // So zero pad the top bits
sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8
sha1_addUncounted(
s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as
sha1_addUncounted(s, s->byteCount >> 13); // byte.
sha1_addUncounted(s, s->byteCount >> 5);
sha1_addUncounted(s, s->byteCount << 3);
}
uint8_t *sha1_result(sha1nfo *s) {
// Pad to complete the last block
sha1_pad(s);
#ifndef SHA_BIG_ENDIAN
// Swap byte order back
int i;
for (i = 0; i < 5; i++) {
s->state[i] = (((s->state[i]) << 24) & 0xff000000) |
(((s->state[i]) << 8) & 0x00ff0000) |
(((s->state[i]) >> 8) & 0x0000ff00) |
(((s->state[i]) >> 24) & 0x000000ff);
}
#endif
// Return pointer to hash (20 characters)
return (uint8_t *)s->state;
}
#define HMAC_IPAD 0x36
#define HMAC_OPAD 0x5c
void sha1_initHmac(sha1nfo *s, const uint8_t *key, int keyLength) {
uint8_t i;
memset(s->keyBuffer, 0, BLOCK_LENGTH);
if (keyLength > BLOCK_LENGTH) {
// Hash long keys
sha1_init(s);
for (; keyLength--;)
sha1_writebyte(s, *key++);
memcpy(s->keyBuffer, sha1_result(s), HASH_LENGTH);
} else {
// Block length keys are used as is
memcpy(s->keyBuffer, key, keyLength);
}
// Start inner hash
sha1_init(s);
for (i = 0; i < BLOCK_LENGTH; i++) {
sha1_writebyte(s, s->keyBuffer[i] ^ HMAC_IPAD);
}
}
uint8_t *sha1_resultHmac(sha1nfo *s) {
uint8_t i;
// Complete inner hash
memcpy(s->innerHash, sha1_result(s), HASH_LENGTH);
// Calculate outer hash
sha1_init(s);
for (i = 0; i < BLOCK_LENGTH; i++)
sha1_writebyte(s, s->keyBuffer[i] ^ HMAC_OPAD);
for (i = 0; i < HASH_LENGTH; i++)
sha1_writebyte(s, s->innerHash[i]);
return sha1_result(s);
}
// End public domain SHA1 implementation
void sha1(const u8 *data, size_t len, u8 *out) {
sha1nfo s;
sha1_init(&s);
sha1_write(&s, (const char *)data, len);
memcpy(out, sha1_result(&s), HASH_LENGTH);
}
char *sha1_hex(const u8 *data, size_t len) {
u8 digest[HASH_LENGTH];
sha1(data, len, digest);
u8 *hex = ck_alloc(HASH_LENGTH * 2 + 1);
for (size_t i = 0; i < HASH_LENGTH; ++i) {
sprintf((char *)(hex + i * 2), "%02x", digest[i]);
}
return hex;
}
char *sha1_hex_for_file(const char *fname, u32 len) {
int fd = open(fname, O_RDONLY);
if (fd < 0) { PFATAL("Unable to open '%s'", fname); }
u32 read_len = MIN(len, (u32)MAX_FILE);
u8 *tmp = ck_alloc(read_len);
ck_read(fd, tmp, read_len, fname);
close(fd);
char *hex = sha1_hex(tmp, read_len);
ck_free(tmp);
return hex;
}

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com> and
Dominik Maier <mail@dmnk.co>
@ -178,7 +178,8 @@ fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv,
void classify_counts(afl_forkserver_t *fsrv) {
u8 *mem = fsrv->trace_bits;
const u8 *map = binary_mode ? count_class_binary : count_class_human;
const u8 *map = (binary_mode || collect_coverage) ? count_class_binary
: count_class_human;
u32 i = map_size;
@ -224,8 +225,13 @@ static void at_exit_handler(void) {
if (remove_shm) {
remove_shm = false;
if (shm.map) afl_shm_deinit(&shm);
if (fsrv->use_shmem_fuzz) deinit_shmem(fsrv, shm_fuzz);
if ((shm_fuzz && shm_fuzz->shmemfuzz_mode) || fsrv->use_shmem_fuzz) {
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
}
}
@ -240,14 +246,7 @@ static void analyze_results(afl_forkserver_t *fsrv) {
u32 i;
for (i = 0; i < map_size; i++) {
if (fsrv->trace_bits[i]) {
total += fsrv->trace_bits[i];
if (fsrv->trace_bits[i] > highest) highest = fsrv->trace_bits[i];
// if (!coverage_map[i]) { coverage_map[i] = 1; }
coverage_map[i] |= fsrv->trace_bits[i];
}
if (fsrv->trace_bits[i]) { coverage_map[i] |= fsrv->trace_bits[i]; }
}
@ -1339,6 +1338,8 @@ int main(int argc, char **argv_orig, char **envp) {
}
if (collect_coverage) { binary_mode = false; } // ensure this
if (optind == argc || !out_file) { usage(argv[0]); }
if (in_dir && in_filelist) { FATAL("you can only specify either -i or -I"); }
@ -1531,6 +1532,8 @@ int main(int argc, char **argv_orig, char **envp) {
/* initialize cmplog_mode */
shm_fuzz->cmplog_mode = 0;
atexit(at_exit_handler);
u8 *map = afl_shm_init(shm_fuzz, MAX_FILE + sizeof(u32), 1);
shm_fuzz->shmemfuzz_mode = true;
if (!map) { FATAL("BUG: Zero return from afl_shm_init."); }
@ -1677,12 +1680,9 @@ int main(int argc, char **argv_orig, char **envp) {
if ((coverage_map = (u8 *)malloc(map_size + 64)) == NULL)
FATAL("coult not grab memory");
edges_only = false;
raw_instr_output = true;
}
atexit(at_exit_handler);
if (get_afl_env("AFL_DEBUG")) {
int j = optind;
@ -1699,9 +1699,12 @@ int main(int argc, char **argv_orig, char **envp) {
map_size = fsrv->map_size;
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz) {
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
}
if (in_dir) {
if (execute_testcases(in_dir) == 0) {
@ -1733,9 +1736,12 @@ int main(int argc, char **argv_orig, char **envp) {
} else {
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz) {
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
}
#ifdef __linux__
if (!fsrv->nyx_mode) {
@ -1782,9 +1788,9 @@ int main(int argc, char **argv_orig, char **envp) {
}
remove_shm = 0;
remove_shm = false;
afl_shm_deinit(&shm);
if (fsrv->use_shmem_fuzz) shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
if (fsrv->use_shmem_fuzz) { shm_fuzz = deinit_shmem(fsrv, shm_fuzz); }
u32 ret;

View File

@ -7,7 +7,7 @@
Forkserver design by Jann Horn <jannhorn@googlemail.com>
Now maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
Andrea Fioraldi <andreafioraldi@gmail.com> and
Dominik Maier <mail@dmnk.co>
@ -82,6 +82,8 @@ static u8 crash_mode, /* Crash-centric mode? */
remove_shm = 1, /* remove shmem on exit? */
debug; /* debug mode */
static u32 del_len_limit = 1; /* Minimum block deletion length */
static volatile u8 stop_soon; /* Ctrl-C pressed? */
static afl_forkserver_t *fsrv;
@ -480,7 +482,7 @@ next_del_blksize:
}
if (del_len > 1 && in_len >= 1) {
if (del_len > del_len_limit && in_len >= 1) {
del_len /= 2;
goto next_del_blksize;
@ -796,8 +798,9 @@ static void usage(u8 *argv0) {
"Minimization settings:\n"
" -e - solve for edge coverage only, ignore hit counts\n"
" -x - treat non-zero exit codes as crashes\n\n"
" -H - minimize a hang (hang mode)\n"
" -l bytes - set minimum block deletion length to speed up minimization\n"
" -x - treat non-zero exit codes as crashes\n"
" -H - minimize a hang (hang mode)\n\n"
"For additional tips, please consult %s/README.md.\n\n"
@ -830,7 +833,8 @@ static void usage(u8 *argv0) {
int main(int argc, char **argv_orig, char **envp) {
s32 opt;
u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0;
u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0,
del_limit_given = 0;
char **use_argv;
char **argv = argv_cpy_dup(argc, argv_orig);
@ -846,7 +850,7 @@ int main(int argc, char **argv_orig, char **envp) {
SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n");
while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeAOQUWXYHh")) > 0) {
while ((opt = getopt(argc, argv, "+i:o:f:m:t:l:B:xeAOQUWXYHh")) > 0) {
switch (opt) {
@ -1055,6 +1059,24 @@ int main(int argc, char **argv_orig, char **envp) {
read_bitmap(optarg, mask_bitmap, map_size);
break;
case 'l':
if (del_limit_given) { FATAL("Multiple -l options not supported"); }
del_limit_given = 1;
if (!optarg) { FATAL("Wrong usage of -l"); }
if (optarg[0] == '-') { FATAL("Dangerously low value of -l"); }
del_len_limit = atoi(optarg);
if (del_len_limit < 1 || del_len_limit > TMIN_MAX_FILE) {
FATAL("Value of -l out of range between 1 and TMIN_MAX_FILE");
}
break;
case 'h':
usage(argv[0]);
return -1;

149
src/hashmap.c Normal file
View File

@ -0,0 +1,149 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "types.h"
#define TABLE_SIZE 10007 // Use a prime number for better distribution
typedef struct HashNode {
uint64_t key;
struct HashNode *next;
} HashNode;
typedef struct HashMap {
HashNode **table;
} HashMap;
static HashMap *_hashmap;
void hashmap_reset() {
if (unlikely(!_hashmap)) {
_hashmap = (HashMap *)malloc(sizeof(HashMap));
_hashmap->table = (HashNode **)malloc(sizeof(HashNode *) * TABLE_SIZE);
memset((char *)_hashmap->table, 0, sizeof(HashNode *) * TABLE_SIZE);
} else {
for (int i = 0; i < TABLE_SIZE; i++) {
HashNode *node = _hashmap->table[i];
while (node) {
HashNode *temp = node;
node = node->next;
free(temp);
}
}
memset((char *)_hashmap->table, 0, sizeof(HashNode *) * TABLE_SIZE);
}
}
static inline unsigned int hash(uint64_t key) {
return key % TABLE_SIZE;
}
// type must be below 8
bool hashmap_search_and_add(uint8_t type, uint64_t key) {
if (unlikely(type >= 8)) return false;
uint64_t val = (key & 0xf8ffffffffffffff) + (type << 56);
unsigned int index = hash(val);
HashNode *node = _hashmap->table[index];
while (node) {
if (node->key == val) return true;
node = node->next;
}
// not found so add it
node = (HashNode *)malloc(sizeof(HashNode));
node->key = val;
node->next = _hashmap->table[index];
_hashmap->table[index] = node;
return false;
}
// type must be below 8
bool hashmap_search_and_add_ptr(uint8_t type, u8 *key) {
if (unlikely(type >= 8)) return false;
uint64_t key_t = 0;
memcpy(((char *)key_t) + (7 - type), key, type + 1);
return hashmap_search_and_add(type, key_t);
}
/* below is not used */
void hashmap_insert(uint64_t key) {
unsigned int index = hash(key);
HashNode *node = (HashNode *)malloc(sizeof(HashNode));
node->key = key;
node->next = _hashmap->table[index];
_hashmap->table[index] = node;
}
bool hashmap_search(uint64_t key) {
unsigned int index = hash(key);
HashNode *node = _hashmap->table[index];
while (node) {
if (node->key == key) return true;
node = node->next;
}
return false;
}
void delete(uint64_t key) {
unsigned int index = hash(key);
HashNode *prev = NULL, *node = _hashmap->table[index];
while (node) {
if (node->key == key) {
if (prev)
prev->next = node->next;
else
_hashmap->table[index] = node->next;
free(node);
return;
}
prev = node;
node = node->next;
}
}
void freeHashMap(HashMap *map) {
free(_hashmap->table);
free(map);
}

View File

@ -10,12 +10,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t i) {
if (i < 15) return -1;
if (buf[0] != 'A') return 0;
if (buf[1] != 'B') return 0;
if (buf[2] != 'C') return 0;
if (buf[3] != 'D') return 0;
int *icmp = (int *)(buf + 4);
int *icmp = (int *)(buf + 1);
if (*icmp != 0x69694141) return 0;
if (memcmp(buf + 8, "1234EF", 6) == 0) abort();
if (memcmp(buf + 5, "1234EF", 6) == 0) abort();
return 0;
}

View File

@ -62,7 +62,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
$ECHO "$RED[!] llvm_mode threadsafe instrumentation failed"
CODE=1
}
rm -f test-instr.ts.0 test-instr.ts.1
rm -f test-instr.ts.0 test-instr.ts.1 test-instr.ts
} || {
$ECHO "$RED[!] llvm_mode (threadsafe) failed"
CODE=1
@ -197,7 +197,8 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
for I in char short int long "long long"; do
for BITS in 8 16 32 64; do
bin="$testcase-split-$I-$BITS.compcov"
AFL_LLVM_INSTRUMENT=AFL AFL_DEBUG=1 AFL_LLVM_LAF_SPLIT_COMPARES_BITW=$BITS AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast -fsigned-char -DINT_TYPE="$I" -o "$bin" "$testcase" > test.out 2>&1;
#AFL_LLVM_INSTRUMENT=AFL
AFL_DEBUG=1 AFL_LLVM_LAF_SPLIT_COMPARES_BITW=$BITS AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast -fsigned-char -DINT_TYPE="$I" -o "$bin" "$testcase" > test.out 2>&1;
if ! test -e "$bin"; then
cat test.out
$ECHO "$RED[!] llvm_mode laf-intel/compcov integer splitting failed! ($testcase with type $I split to $BITS)!";
@ -263,13 +264,12 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
}
rm -f test-compcov test.out instrumentlist.txt
AFL_LLVM_CMPLOG=1 ../afl-clang-fast -o test-cmplog test-cmplog.c > /dev/null 2>&1
../afl-clang-fast -O0 -o test-c test-cmplog.c > /dev/null 2>&1
test -e test-cmplog && {
$ECHO "$GREY[*] running afl-fuzz for llvm_mode cmplog, this will take approx 10 seconds"
{
mkdir -p in
echo 00000000000000000000000000000000 > in/in
AFL_BENCH_UNTIL_CRASH=1 ../afl-fuzz -l 3 -m none -V30 -i in -o out -c ./test-cmplog -- ./test-c >>errors 2>&1
AFL_BENCH_UNTIL_CRASH=1 ../afl-fuzz -Z -l 3 -m none -V30 -i in -o out -c 0 -- ./test-cmplog >>errors 2>&1
} >>errors 2>&1
test -n "$( ls out/default/crashes/id:000000* out/default/hangs/id:000000* 2>/dev/null )" && {
$ECHO "$GREEN[+] afl-fuzz is working correctly with llvm_mode cmplog"
@ -284,7 +284,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
$ECHO "$YELLOW[-] we cannot test llvm_mode cmplog because it is not present"
INCOMPLETE=1
}
rm -rf errors test-cmplog test-c in core.*
rm -rf errors test-cmplog in core.*
../afl-clang-fast -o test-persistent ../utils/persistent_mode/persistent_demo.c > /dev/null 2>&1
test -e test-persistent && {
echo foo | AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && {

View File

@ -63,7 +63,7 @@ test -e ../afl-qemu-trace && {
{
export AFL_PRELOAD=../libcompcov.so
export AFL_COMPCOV_LEVEL=2
../afl-fuzz -m ${MEM_LIMIT} -V07 -Q -i in -o out -- ./test-compcov >>errors 2>&1
AFL_NO_UI=1 ../afl-fuzz -V07 -Q -i in -o out -- ./test-compcov 2>&1
unset AFL_PRELOAD
unset AFL_COMPCOV_LEVEL
} >>errors 2>&1
@ -88,7 +88,7 @@ test -e ../afl-qemu-trace && {
test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" -o "$SYS" = "aarch64" -o ! "${SYS%%arm*}" && {
$ECHO "$GREY[*] running afl-fuzz for qemu_mode cmplog, this will take approx 10 seconds"
{
../afl-fuzz -m none -V07 -Q -c 0 -l 3 -i in -o out -- ./test-compcov >>errors 2>&1
../afl-fuzz -V07 -Q -c 0 -l 3 -i in -o out -- ./test-compcov >>errors 2>&1
} >>errors 2>&1
test -n "$( ls out/default/queue/id:000001* 2>/dev/null )" && {
$ECHO "$GREEN[+] afl-fuzz is working correctly with qemu_mode cmplog"

View File

@ -1 +1 @@
63aab0f
4b4fdab1

View File

@ -198,10 +198,12 @@ $MAKECMD -j1 || exit 1
echo "[+] Build process successful!"
echo "[*] Installing Unicorn python bindings..."
XOPT=
$PYTHONBIN -m pip install --help 2>/dev/null | grep -q break-system-packages && XOPT=--break-system-packages
cd unicorn/bindings/python || exit 1
if [ -z "$VIRTUAL_ENV" ]; then
echo "[*] Info: Installing python unicornafl using --user"
THREADS=$CORES $PYTHONBIN -m pip install --user --force .|| exit 1
THREADS=$CORES $PYTHONBIN -m pip install --user $XOPT --force .|| exit 1
else
echo "[*] Info: Installing python unicornafl to virtualenv: $VIRTUAL_ENV"
THREADS=$CORES $PYTHONBIN -m pip install --force .|| exit 1
@ -211,7 +213,7 @@ echo "[*] Installing Unicornafl python bindings..."
cd bindings/python || exit 1
if [ -z "$VIRTUAL_ENV" ]; then
echo "[*] Info: Installing python unicornafl using --user"
THREADS=$CORES $PYTHONBIN -m pip install --user --force .|| exit 1
THREADS=$CORES $PYTHONBIN -m pip install --user $XOPT --force .|| exit 1
else
echo "[*] Info: Installing python unicornafl to virtualenv: $VIRTUAL_ENV"
THREADS=$CORES $PYTHONBIN -m pip install --force .|| exit 1

View File

@ -89,8 +89,8 @@ def dump_arch_info():
def dump_regs():
reg_state = {}
for reg in current_arch.all_registers:
reg_val = get_register(reg)
for reg in gef.arch.registers:
reg_val = gef.arch.register(reg)
reg_state[reg.strip().strip("$")] = reg_val
return reg_state
@ -101,7 +101,9 @@ def dump_process_memory(output_dir):
final_segment_list = []
# GEF:
vmmap = get_process_maps()
vmmap = gef.memory.maps
memory = GefMemoryManager()
if not vmmap:
print("No address mapping information found")
return final_segment_list
@ -126,7 +128,7 @@ def dump_process_memory(output_dir):
if entry.is_readable() and not "(deleted)" in entry.path:
try:
# Compress and dump the content to a file
seg_content = read_memory(entry.page_start, entry.size)
seg_content = memory.read(entry.page_start, entry.size)
if seg_content == None:
print(
"Segment empty: @0x{0:016x} (size:UNKNOWN) {1}".format(

Some files were not shown because too many files have changed in this diff Show More