Coder Social home page Coder Social logo

luzer's People

Contributors

azanegin avatar ligurio avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

luzer's Issues

Fix building with LuaJIT

[ 53%] Building C object luzer/CMakeFiles/luzer.dir/luzer.c.o
/home/sergeyb/sources/luzer/luzer/luzer.c:57:1: error: static declaration of 'luaL_traceback' follows non-static declaration
luaL_traceback(lua_State *L) {
^
/home/sergeyb/sources/luzer/build/luajit-v2.1/source/src/lauxlib.h:86:17: note: previous declaration is here
LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
                ^
/home/sergeyb/sources/luzer/luzer/luzer.c:126:18: error: too few arguments to function call, expected 4, have 1
        luaL_traceback(L);
        ~~~~~~~~~~~~~~  ^
/home/sergeyb/sources/luzer/build/luajit-v2.1/source/src/lauxlib.h:86:17: note: 'luaL_traceback' declared here
LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, const char *msg,
                ^
2 errors generated.

Fix building rock

Install the project...
-- Install configuration: "RelWithDebInfo"
-- Installing: /home/runner/.luarocks/lib/luarocks/rocks-5.2/luzer/scm-1/lua/doc/README.md
-- Installing: /home/runner/.luarocks/lib/luarocks/rocks-5.2/luzer/scm-1/lua/doc/api.md
-- Installing: /home/runner/.luarocks/lib/luarocks/rocks-5.2/luzer/scm-1/lua/doc/grammar_based_fuzzing.md
-- Installing: /home/runner/.luarocks/lib/luarocks/rocks-5.2/luzer/scm-1/lua/doc/index.md
-- Installing: /home/runner/.luarocks/lib/luarocks/rocks-5.2/luzer/scm-1/lua/doc/test_management.md
-- Installing: /home/runner/.luarocks/lib/luarocks/rocks-5.2/luzer/scm-1/lua/doc/usage.md
-- Installing: /home/runner/.luarocks/lib/luarocks/rocks-5.2/luzer/scm-1/lua/mutator/mutator.c
-- Installing: /home/runner/.luarocks/lib/luarocks/rocks-5.2/luzer/scm-1/lua/mutator/crossover.c
-- Installing: /home/runner/.luarocks/lib/luarocks/rocks-5.2/luzer/scm-1/lib/luzer.so
-- Installing: /home/runner/.luarocks/lib/luarocks/rocks-5.2/luzer/scm-1/lib/libcustom_mutator.so.1.0.0
-- Installing: /home/runner/.luarocks/lib/luarocks/rocks-5.2/luzer/scm-1/lib/libcustom_mutator.so.1

luzer scm-1 depends on lua >= 5.1 (5.2-1 provided by VM)
cp: cannot stat '/home/runner/.luarocks/lib/luarocks/rocks-5.2/luzer/scm-1/lib/libcustom_mutator.so.1': No such file or directory

Error: Failed copying /home/runner/.luarocks/lib/luarocks/rocks-5.2/luzer/scm-1/lib/libcustom_mutator.so.1 to /home/runner/.luarocks/lib/lua/5.2/libcustom_mutator.so.1
Error: Process completed with exit code 1.

Github actions clang version mismatch

-- The C compiler identification is Clang 14.0.0
-- The CXX compiler identification is Clang 14.0.0
8<============cut===============
-- Found LLVM 15.0.[7](https://github.com/ligurio/luzer/actions/runs/7240171193/job/19794688179#step:8:8)
-- Found libclang_rt /usr/lib/llvm-15/lib/clang/15.0.7/lib/linux/libclang_rt.fuzzer_no_main-x[8](https://github.com/ligurio/luzer/actions/runs/7240171193/job/19794688179#step:8:9)6_64.a
-- Configuring done (4.5s)
-- Generating done (0.0s)
-- Build files have been written to: /home/runner/work/luzer/luzer/build

I'm not sure about that, but possibly Testing action uses clang-14 to link with libclang_rt-15.

__sanitizer_cov_8bit_counters_init never invoked for interpreter

Will provide PR to fix in some time.

The __sanitizer_cov_8bit_counters_init() is a hook that LLVM SanitizerCoverage uses to point client code to inline counters that are incremented by instrumented code (well, when used 8bit-inline-ctrs instrumentation). Counters are usually allocated as a separate DSO section.

00000000000558c3 d __start___sancov_cntrs
0000000000055968 d __start___sancov_pcs
0000000000055961 d __stop___sancov_cntrs
0000000000056348 d __stop___sancov_pcs
000000000000e100 t sancov.module_ctor_8bit_counters

LibFuzzer uses this hook to a add those counters to monitored list. Global DSO-wide constructor inside sancov.module_ctor_8bit_counters in each loaded module calls this hook with pointers to ctrs section.

Code located here

TestOneInput(const uint8_t* data, size_t size) {

also invoke __sanitizer_cov_8bit_counters_init(). This is most likely intended for pointing to libfuzzer the region of counters that is used for interpreted code of the lua script.

Running test script outputs the following:

Starting program: /usr/bin/lua ../../luzer/tests/test_e2e.lua
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 2552143800
INFO: Loaded 1 modules   (158 inline 8-bit counters): 158 [0x7ffff7c2f8c3, 0x7ffff7c2f961),
INFO: Loaded 1 PC tables (158 PCs): 158 [0x7ffff7c2f968,0x7ffff7c30348),
[New Thread 0x7ffff622a6c0 (LWP 298)]
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
INFO: A corpus is not provided, starting from an empty corpus
#2      INITED cov: 32 ft: 33 corp: 1/1b exec/s: 0 rss: 36Mb
#7      NEW    cov: 33 ft: 34 corp: 2/2b lim: 4 exec/s: 0 rss: 36Mb L: 1/1 MS: 5 ShuffleBytes-ChangeByte-ShuffleBytes-CrossOver-ChangeBit-
#30     NEW    cov: 34 ft: 36 corp: 3/3b lim: 4 exec/s: 0 rss: 36Mb L: 1/1 MS: 3 ChangeByte-CopyPart-ChangeByte-
        NEW_FUNC[1/1]: 0x7ffff7be9161
#76     NEW    cov: 36 ft: 39 corp: 4/5b lim: 4 exec/s: 0 rss: 36Mb L: 2/2 MS: 1 InsertByte-
#78     NEW    cov: 36 ft: 42 corp: 5/7b lim: 4 exec/s: 0 rss: 36Mb L: 2/2 MS: 2 CrossOver-EraseBytes-
#124    NEW    cov: 36 ft: 44 corp: 6/8b lim: 4 exec/s: 0 rss: 36Mb L: 1/2 MS: 1 EraseBytes-

This creates a false impression that mmap-ed counters for lua code are working. As I pointed out above, each instrumented DSO should call the hook once. Then, luzer.so code should call the hook for dynamic counters. This is not the case.

root@trixie:~/luzer/build/luzer# gdb /usr/bin/lua
GNU gdb (Debian 13.2-1) 13.2
8<==============cut==================
(No debugging symbols found in /usr/bin/lua)
(gdb) b __sanitizer_cov_8bit_counters_init
Function "__sanitizer_cov_8bit_counters_init" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (__sanitizer_cov_8bit_counters_init) pending.
(gdb) run ../../luzer/tests/test_e2e.lua
Starting program: /usr/bin/lua ../../luzer/tests/test_e2e.lua
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, 0x00007ffff7c1a3e8 in __sanitizer_cov_8bit_counters_init () from ./luzer.so
(gdb) bt
#0  0x00007ffff7c1a3e8 in __sanitizer_cov_8bit_counters_init () from ./luzer.so
#1  0x00007ffff7be8117 in sancov.module_ctor_8bit_counters () from ./luzer.so
#2  0x00007ffff7fcfd2e in call_init (env=0x7fffffffed10, argv=0x7fffffffecf8, argc=2, l=<optimized out>) at ./elf/dl-init.c:90
#3  call_init (l=<optimized out>, argc=2, argv=0x7fffffffecf8, env=0x7fffffffed10) at ./elf/dl-init.c:27
#4  0x00007ffff7fcfe14 in _dl_init (main_map=0x555555592280, argc=2, argv=0x7fffffffecf8, env=0x7fffffffed10) at ./elf/dl-init.c:137
#5  0x00007ffff7fcc516 in __GI__dl_catch_exception (exception=exception@entry=0x0, operate=operate@entry=0x7ffff7fd6570 <call_dl_init>, args=args@entry=0x7fffffffe0b0) at ./elf/dl-catch.c:211
#6  0x00007ffff7fd650e in dl_open_worker (a=a@entry=0x7fffffffe250) at ./elf/dl-open.c:808
#7  0x00007ffff7fcc489 in __GI__dl_catch_exception (exception=exception@entry=0x7fffffffe230, operate=operate@entry=0x7ffff7fd6480 <dl_open_worker>, args=args@entry=0x7fffffffe250) at ./elf/dl-catch.c:237
#8  0x00007ffff7fd68a8 in _dl_open (file=0x555555592158 "./luzer.so", mode=<optimized out>, caller_dlopen=0x55555557972b, nsid=<optimized out>, argc=2, argv=0x7fffffffecf8, env=0x7fffffffed10) at ./elf/dl-open.c:884
#9  0x00007ffff7d236f8 in dlopen_doit (a=a@entry=0x7fffffffe4c0) at ./dlfcn/dlopen.c:56
#10 0x00007ffff7fcc489 in __GI__dl_catch_exception (exception=exception@entry=0x7fffffffe420, operate=0x7ffff7d236a0 <dlopen_doit>, args=0x7fffffffe4c0) at ./elf/dl-catch.c:237
#11 0x00007ffff7fcc5af in _dl_catch_error (objname=0x7fffffffe478, errstring=0x7fffffffe480, mallocedp=0x7fffffffe477, operate=<optimized out>, args=<optimized out>) at ./elf/dl-catch.c:256
#12 0x00007ffff7d231e7 in _dlerror_run (operate=operate@entry=0x7ffff7d236a0 <dlopen_doit>, args=args@entry=0x7fffffffe4c0) at ./dlfcn/dlerror.c:138
#13 0x00007ffff7d237a9 in dlopen_implementation (dl_caller=<optimized out>, mode=<optimized out>, file=<optimized out>) at ./dlfcn/dlopen.c:71
#14 ___dlopen (file=<optimized out>, mode=<optimized out>) at ./dlfcn/dlopen.c:81
#15 0x000055555557972b in ?? ()
8<=======cut============
#37 0x000055555555a7ba in ?? ()
(gdb) c
Continuing.
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 3118463730
INFO: Loaded 1 modules   (158 inline 8-bit counters): 158 [0x7ffff7c2f8c3, 0x7ffff7c2f961),
INFO: Loaded 1 PC tables (158 PCs): 158 [0x7ffff7c2f968,0x7ffff7c30348),
[New Thread 0x7ffff622a6c0 (LWP 391)]
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
INFO: A corpus is not provided, starting from an empty corpus
#2      INITED cov: 32 ft: 33 corp: 1/1b exec/s: 0 rss: 70Mb
#23     NEW    cov: 33 ft: 34 corp: 2/2b lim: 4 exec/s: 0 rss: 70Mb L: 1/1 MS: 1 ChangeBinInt-
        NEW_FUNC[1/1]: 0x7ffff7be9161
#77     NEW    cov: 35 ft: 37 corp: 3/5b lim: 4 exec/s: 0 rss: 70Mb L: 3/3 MS: 4 CrossOver-InsertByte-ChangeByte-ChangeByte-
8<=====cut========
/usr/bin/lua: ../../luzer/tests/test_e2e.lua:7: assert has triggered
stack traceback:
        [C]: in function 'assert'
        ../../luzer/tests/test_e2e.lua:7: in function <../../luzer/tests/test_e2e.lua:3>
        [C]: in function 'Fuzz'
        ../../luzer/tests/test_e2e.lua:15: in main chunk
        [C]: ?
==390== ERROR: libFuzzer: fuzz target exited
[Thread 0x7ffff622a6c0 (LWP 391) exited]
[Inferior 1 (process 390) exited with code 0115]

As we can see here, _init() hook is called just once. And this call is from none other place than luzer.so DSO constructor. No call for mmap-ed counters ever made. Why?

if (counter_index_registered >= next_index) {

This condition is always true, as (contrast to atheris) in this code no counters are ever registered.

Basically, right now the Lua "debug hook instrumentation" is useless. Only way it ever reaches LibFuzzer is via another bug: #11

But luzer works for compiled, native lua modules, that were build with SanCov and register their own counters.

Incorrect parsing of Libfuzzer flags

In the process of adding fuzzing flags, one of the flags was not parsed.

Example:

script lua:

local luzer = require("luzer")

local function TestOneInput(buf)
    local fdp = luzer.FuzzedDataProvider(buf)
    local str = fdp:consume_string(1)
    if str == "c" then
                assert(nil, "assert has triggered")
    end
    return
end

local opts = {
    --print_pcs = 1,
    --max_len = 4096,
    dd = 1,
    help = 1,
    print_pcs = 1,
}
luzer.Fuzz(TestOneInput, nil, opts)

Output log:

root@trixie:~/luzer/build/luzer# gdb /usr/bin/lua
GNU gdb (Debian 13.2-1) 13.2
Copyright (C) 2023 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /usr/bin/lua...
Reading symbols from /usr/lib/debug/.build-id/97/c1063cf4058d17818dfa6325429bb6cdca9080.debug...
(gdb) run ../../luzer/tests/test_e2e.lua
Starting program: /usr/bin/lua ../../luzer/tests/test_e2e.lua
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".


WARNING: unrecognized flag '-dd=1'; use -help=1 to list all flags

Usage:

To run fuzzing pass 0 or more directories.
-print_pcs=1 [-flag1=val1 [-flag2=val2 ...] ] [dir1 [dir2 ...] ]

To run individual tests without fuzzing pass 1 or more files:
-print_pcs=1 [-flag1=val1 [-flag2=val2 ...] ] file1 [file2 ...]

Flags: (strictly in form -flag=value)
 verbosity                              1       Verbosity level.
 seed                                   0       Random seed. If 0, seed is generated.
 runs                                   -1      Number of individual test runs (-1 for infinite runs).
 max_len                                0       Maximum length of the test input. If 0, libFuzzer tries to guess a good value based on the corpus and reports it.
 len_control                            100     Try generating small inputs first, then try larger inputs over time.  Specifies the rate at which the length limit is increased (smaller == faster).  If 0, immediately try inputs with size up to max_len. Default value is 0, if LLVMFuzzerCustomMutator is used.
 seed_inputs                            0       A comma-separated list of input files to use as an additional seed corpus. Alternatively, an "@" followed by the name of a file containing the comma-separated list.
 keep_seed                              0       If 1, keep seed inputs in the corpus even if they do not produce new coverage. When used with |reduce_inputs==1|, the seed inputs will never be reduced. This option can be useful when seeds arenot properly formed for the fuzz target but still have useful snippets.
 cross_over                             1       If 1, cross over inputs.
 cross_over_uniform_dist                0       Experimental. If 1, use a uniform probability distribution when choosing inputs to cross over with. Some of the inputs in the corpus may never get chosen for mutation depending on the input mutation scheduling policy. With this flag, all inputs, regardless of the input mutation scheduling policy, can be chosen as an input to cross over with. This can be particularly useful with |keep_seed==1|; all the initial seed inputs, even though they do not increase coverage because they are not properly formed, will still be chosen as an input to cross over with.
 mutate_depth                           5       Apply this number of consecutive mutations to each input.
 reduce_depth                           0       Experimental/internal. Reduce depth if mutations lose unique features
 shuffle                                1       Shuffle inputs at startup
 prefer_small                           1       If 1, always prefer smaller inputs during the corpus shuffle.
 timeout                                1200    Timeout in seconds (if positive). If one unit runs more than this number of seconds the process will abort.
 error_exitcode                         77      When libFuzzer itself reports a bug this exit code will be used.
 timeout_exitcode                       70      When libFuzzer reports a timeout this exit code will be used.
 max_total_time                         0       If positive, indicates the maximal total time in seconds to run the fuzzer.
 help                                   0       Print help.
 fork                                   0       Experimental mode where fuzzing happens in a subprocess
 fork_corpus_groups                     0       For fork mode, enable the corpus-group strategy, The main corpus will be grouped according to size, and each sub-process will randomly select seeds from different groups as the sub-corpus.
 ignore_timeouts                        1       Ignore timeouts in fork mode
 ignore_ooms                            1       Ignore OOMs in fork mode
 ignore_crashes                         0       Ignore crashes in fork mode
 merge                                  0       If 1, the 2-nd, 3-rd, etc corpora will be merged into the 1-st corpus. Only interesting units will be taken. This flag can be used to minimize a corpus.
 set_cover_merge                        0       If 1, the 2-nd, 3-rd, etc corpora will be merged into the 1-st corpus. Same as the 'merge' flag, but uses the standard greedy algorithm for the set cover problem to compute an approximation of the minimum set of testcases that provide the same coverage as the initial corpora
 stop_file                              0       Stop fuzzing ASAP if this file exists
 merge_control_file                     0       Specify a control file used for the merge process. If a merge process gets killed it tries to leave this file in a state suitable for resuming the merge. By default a temporary file will be used.The same file can be used for multistep merge process.
 minimize_crash                         0       If 1, minimizes the provided crash input. Use with -runs=N or -max_total_time=N to limit the number attempts. Use with -exact_artifact_path to specify the output. Combine with ASAN_OPTIONS=dedup_token_length=3 (or similar) to ensure that the minimized input triggers the same crash.
 cleanse_crash                          0       If 1, tries to cleanse the provided crash input to make it contain fewer original bytes. Use with -exact_artifact_path to specify the output.
 mutation_graph_file                    0       Saves a graph (in DOT format) to mutation_graph_file. The graph contains a vertex for each input that has unique coverage; directed edges are provided between parents and children where the child has unique coverage, and are recorded with the type of mutation that caused the child.
 use_counters                           1       Use coverage counters
 use_memmem                             1       Use hints from intercepting memmem, strstr, etc
 use_value_profile                      0       Experimental. Use value profile to guide fuzzing.
 use_cmp                                1       Use CMP traces to guide mutations
 shrink                                 0       Experimental. Try to shrink corpus inputs.
 reduce_inputs                          1       Try to reduce the size of inputs while preserving their full feature sets
 jobs                                   0       Number of jobs to run. If jobs >= 1 we spawn this number of jobs in separate worker processes with stdout/stderr redirected to fuzz-JOB.log.
 workers                                0       Number of simultaneous worker processes to run the jobs. If zero, "min(jobs,NumberOfCpuCores()/2)" is used.
 reload                                 1       Reload the main corpus every <N> seconds to get new units discovered by other processes. If 0, disabled
 report_slow_units                      10      Report slowest units if they run for more than this number of seconds.
 only_ascii                             0       If 1, generate only ASCII (isprint+isspace) inputs.
 dict                                   0       Experimental. Use the dictionary file.
 artifact_prefix                        0       Write fuzzing artifacts (crash, timeout, or slow inputs) as $(artifact_prefix)file
 exact_artifact_path                    0       Write the single artifact on failure (crash, timeout) as $(exact_artifact_path). This overrides -artifact_prefix and will not use checksum in the file name. Do not use the same path for several parallel processes.
 print_pcs                              0       If 1, print out newly covered PCs.
 print_funcs                            2       If >=1, print out at most this number of newly covered functions.
 print_final_stats                      0       If 1, print statistics at exit.
 print_corpus_stats                     0       If 1, print statistics on corpus elements at exit.
 print_coverage                         0       If 1, print coverage information as text at exit.
 print_full_coverage                    0       If 1, print full coverage information (all branches) as text at exit.
 dump_coverage                          0       Deprecated.
 handle_segv                            1       If 1, try to intercept SIGSEGV.
 handle_bus                             1       If 1, try to intercept SIGBUS.
 handle_abrt                            1       If 1, try to intercept SIGABRT.
 handle_ill                             1       If 1, try to intercept SIGILL.
 handle_fpe                             1       If 1, try to intercept SIGFPE.
 handle_int                             1       If 1, try to intercept SIGINT.
 handle_term                            1       If 1, try to intercept SIGTERM.
 handle_xfsz                            1       If 1, try to intercept SIGXFSZ.
 handle_usr1                            1       If 1, try to intercept SIGUSR1.
 handle_usr2                            1       If 1, try to intercept SIGUSR2.
 handle_winexcept                       1       If 1, try to intercept uncaught Windows Visual C++ Exceptions.
 close_fd_mask                          0       If 1, close stdout at startup; if 2, close stderr; if 3, close both. Be careful, this will also close e.g. stderr of asan.
 detect_leaks                           1       If 1, and if LeakSanitizer is enabled try to detect memory leaks during fuzzing (i.e. not only at shut down).
 purge_allocator_interval               1       Purge allocator caches and quarantines every <N> seconds. When rss_limit_mb is specified (>0), purging starts when RSS exceeds 50% of rss_limit_mb. Pass purge_allocator_interval=-1 to disable this functionality.
 trace_malloc                           0       If >= 1 will print all mallocs/frees. If >= 2 will also print stack traces.
 rss_limit_mb                           2048    If non-zero, the fuzzer will exit uponreaching this limit of RSS memory usage.
 malloc_limit_mb                        0       If non-zero, the fuzzer will exit if the target tries to allocate this number of Mb with one malloc call. If zero (default) same limit as rss_limit_mb is applied.
 exit_on_src_pos                        0       Exit if a newly found PC originates from the given source location. Example: -exit_on_src_pos=foo.cc:123. Used primarily for testing libFuzzer itself.
 exit_on_item                           0       Exit if an item with a given sha1 sum was added to the corpus. Used primarily for testing libFuzzer itself.
 ignore_remaining_args                  0       If 1, ignore all arguments passed after this one. Useful for fuzzers that need to do their own argument parsing.
 focus_function                         0       Experimental. Fuzzing will focus on inputs that trigger calls to this function. If -focus_function=auto and -data_flow_trace is used, libFuzzer will choose the focus functions automatically. Disables -entropic when specified.
 entropic                               1       Enables entropic power schedule.
 entropic_feature_frequency_threshold   255     Experimental. If entropic is enabled, all features which are observed less often than the specified value are considered as rare.
 entropic_number_of_rarest_features     100     Experimental. If entropic is enabled, we keep track of the frequencies only for the Top-X least abundant features (union features that are considered as rare).
 entropic_scale_per_exec_time           0       Experimental. If 1, the Entropic power schedule gets scaled based on the input execution time. Inputs with lower execution time get scheduled more (up to 30x). Note that, if 1, fuzzer stops from being deterministic even if a non-zero random seed is given.
 analyze_dict                           0       Experimental
 use_clang_coverage                     0       Deprecated; don't use
 data_flow_trace                        0       Experimental: use the data flow trace
 collect_data_flow                      0       Experimental: collect the data flow trace
 create_missing_dirs                    0       Automatically attempt to create directories for arguments that would normally expect them to already exist (i.e. artifact_prefix, exact_artifact_path, features_dir, corpus)

Flags starting with '--' will be ignored and will be passed verbatim to subprocesses.
free(): invalid pointer

Program received signal SIGABRT, Aborted.
__pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
44      ./nptl/pthread_kill.c: No such file or directory.
(gdb) bt
#0  __pthread_kill_implementation (threadid=<optimized out>, signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
#1  0x00007ffff7d2915f in __pthread_kill_internal (signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:78
#2  0x00007ffff7cdb472 in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#3  0x00007ffff7cc54b2 in __GI_abort () at ./stdlib/abort.c:79
#4  0x00007ffff7cc61ed in __libc_message (fmt=fmt@entry=0x7ffff7e3878c "%s\n") at ../sysdeps/posix/libc_fatal.c:150
#5  0x00007ffff7d32a75 in malloc_printerr (str=str@entry=0x7ffff7e3622c "free(): invalid pointer") at ./malloc/malloc.c:5658
#6  0x00007ffff7d347f4 in _int_free (av=<optimized out>, p=<optimized out>, have_lock=have_lock@entry=0) at ./malloc/malloc.c:4432
#7  0x00007ffff7d3716f in __GI___libc_free (mem=<optimized out>) at ./malloc/malloc.c:3367
#8  0x000055555556c119 in l_alloc (ud=<optimized out>, ptr=<optimized out>, osize=<optimized out>, nsize=<optimized out>) at ./src/lauxlib.c:631
#9  0x000055555556373e in luaM_realloc_ (L=L@entry=0x5555555872a0, block=<optimized out>, osize=16, nsize=nsize@entry=0) at ./src/lmem.c:79
#10 0x00005555555680df in luaH_free (L=L@entry=0x5555555872a0, t=t@entry=0x5555555911c0) at ./src/ltable.c:377
#11 0x00005555555625db in freeobj (o=0x5555555911c0, L=0x5555555872a0) at ./src/lgc.c:383
#12 sweeplist (L=L@entry=0x5555555872a0, p=p@entry=0x555555587380, count=18446744073709551601, count@entry=18446744073709551613) at ./src/lgc.c:424
#13 0x000055555556343f in luaC_freeall (L=L@entry=0x5555555872a0) at ./src/lgc.c:487
#14 0x00005555555673be in close_state (L=0x5555555872a0) at ./src/lstate.c:108
#15 0x0000555555567899 in lua_close (L=<optimized out>) at ./src/lstate.c:212
#16 0x000055555555a6f6 in main (argc=2, argv=0x7fffffffecf8) at ./src/lua.c:389

Problems:

  1. Incorrect output for help flag:
    Result in script: -print_pcs=1 [-flag1=val1 [-flag2=val2 ...] ] [dir1 [dir2 ...] ]
    Expected result: ../../examples/example_basic.lua [-flag1=val1 [-flag2=val2 ...] ] [dir1 [dir2 ...] ]
    Script processed the first flag as name of program file
  2. Incorrect ending fuzz process:
    Result in script:
free(): invalid pointer

Program received signal SIGABRT, Aborted.

undefined symbol when loading luzer

When trying to require luzer, I get the following error:

lua: error loading module 'luzer' from file '/home/xerool/test/luzer/tree/lib/lua/5.4/luzer.so':
        /home/xerool/test/luzer/tree/lib/lua/5.4/luzer.so: undefined symbol: _Z14lua_pushstringP9lua_StatePKc
stack traceback:
        [C]: in ?
        [C]: in function 'require'
        fuzzme.lua:1: in main chunk
        [C]: in ?

Looks like some name mangling has been messed up? I'm not sure how to address this.
The fuzzme.lua file only has require("luzer") as its contents.

For reference, I'm trying to build on arch linux.
Here's the logs from building luzer, which I thought might be helpful because it contains all the library versions I am using.

luzer scm-1 depends on lua >= 5.1 (5.4-1 provided by VM)
-- The C compiler identification is Clang 15.0.7
-- The CXX compiler identification is Clang 15.0.7
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/clang - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/clang++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found Lua: /usr/lib/liblua5.4.so;/usr/lib/libm.so (found suitable version "5.4.6", minimum required is "5.1")
-- Performing Test HAVE_FFI_CALL
-- Performing Test HAVE_FFI_CALL - Success
-- Found FFI: /usr/lib/libffi.so
-- Performing Test Terminfo_LINKABLE
-- Performing Test Terminfo_LINKABLE - Success
-- Found Terminfo: /usr/lib/libtinfo.so
-- Found ZLIB: /usr/lib/libz.so (found version "1.2.13")
-- Found zstd: /usr/lib/libzstd.so
-- Found LibXml2: /usr/lib/libxml2.so (found version "2.10.4")
-- Found Lua 5.4.6
-- Found Lua interpreter /usr/bin/lua5.4
-- Found LLVM 15.0.7
-- Found libclang_rt /usr/lib/clang/15.0.7/lib/linux/libclang_rt.fuzzer_no_main-x86_64.a
-- Configuring done (0.4s)
-- Generating done (0.0s)
-- Build files have been written to: /tmp/luarocks_luzer-scm-1-vzW8Om/luzer/build.luarocks
[ 12%] Building C object luzer/CMakeFiles/luzer.dir/luzer.c.o
[ 25%] Building CXX object luzer/CMakeFiles/luzer.dir/fuzzed_data_provider.cc.o
[ 37%] Building C object luzer/CMakeFiles/luzer.dir/tracer.c.o
[ 50%] Building C object luzer/CMakeFiles/luzer.dir/counters.c.o
[ 62%] Building C object luzer/CMakeFiles/luzer.dir/version.c.o
[ 75%] Linking CXX shared library luzer.so
[ 75%] Built target luzer
[ 87%] Building C object luzer/CMakeFiles/custom_mutator.dir/custom_mutator_lib.c.o
[100%] Linking C shared library libcustom_mutator.so
[100%] Built target custom_mutator
[ 75%] Built target luzer
[100%] Built target custom_mutator
Install the project...

The build completes successfully, of course, but it produces the broken .so file that crashes when required.

Dirty cov collection from fuzzer internals

Please see PR #10 with a small fix.

Insufficient compiler directives to disable coverage instrumentation result in both less performance and worse fuzzing experience (due to messing up real coverage).

I compiled luzer in two different environments. First, as per CONTRIBUTION.md, a Debian (trixie, as only trixie has clang-17 in repos) with liblua-dev version 5.1. Second, as per GitHub Actions yaml file, Ubuntu 22.04 with liblua-dev version 5.2, and whatever clang were in that yaml (15?)

This is objdump from Debian/selfbuild version:

0000000000011030 <increment_counter>:
   11030:       55                      push   %rbp
   11031:       48 89 e5                mov    %rsp,%rbp
   11034:       8a 05 6c 49 04 00       mov    0x4496c(%rip),%al        # 559a6 <__TMC_END__+0xde>
   1103a:       04 01                   add    $0x1,%al
   1103c:       88 05 64 49 04 00       mov    %al,0x44964(%rip)        # 559a6 <__TMC_END__+0xde>
   11042:       89 7d fc                mov    %edi,-0x4(%rbp)
   11045:       48 8b 05 5c 3e 04 00    mov    0x43e5c(%rip),%rax        # 54ea8 <counters@@Base-0x1b78>
   1104c:       48 83 38 00             cmpq   $0x0,(%rax)
   11050:       0f 85 13 00 00 00       jne    11069 <increment_counter+0x39>
   11056:       8a 05 4b 49 04 00       mov    0x4494b(%rip),%al        # 559a7 <__TMC_END__+0xdf>
   1105c:       04 01                   add    $0x1,%al
   1105e:       88 05 43 49 04 00       mov    %al,0x44943(%rip)        # 559a7 <__TMC_END__+0xdf>
   11064:       e9 5d 00 00 00          jmp    110c6 <increment_counter+0x96>
   11069:       48 8b 05 48 3e 04 00    mov    0x43e48(%rip),%rax        # 54eb8 <pctable@@Base-0x1b70>
   11070:       48 83 38 00             cmpq   $0x0,(%rax)
   11074:       0f 85 13 00 00 00       jne    1108d <increment_counter+0x5d>
   1107a:       8a 05 28 49 04 00       mov    0x44928(%rip),%al        # 559a8 <__TMC_END__+0xe0>
   11080:       04 01                   add    $0x1,%al
   11082:       88 05 20 49 04 00       mov    %al,0x44920(%rip)        # 559a8 <__TMC_END__+0xe0>
   11088:       e9 39 00 00 00          jmp    110c6 <increment_counter+0x96>
   1108d:       8a 05 16 49 04 00       mov    0x44916(%rip),%al        # 559a9 <__TMC_END__+0xe1>
   11093:       04 01                   add    $0x1,%al
   11095:       88 05 0e 49 04 00       mov    %al,0x4490e(%rip)        # 559a9 <__TMC_END__+0xe1>
   1109b:       48 8b 05 06 3e 04 00    mov    0x43e06(%rip),%rax        # 54ea8 <counters@@Base-0x1b78>
   110a2:       48 8b 00                mov    (%rax),%rax
   110a5:       48 89 45 f0             mov    %rax,-0x10(%rbp)
   110a9:       8b 45 fc                mov    -0x4(%rbp),%eax
   110ac:       48 8b 0d 75 3e 04 00    mov    0x43e75(%rip),%rcx        # 54f28 <max_counters@@Base-0x1af0>
   110b3:       99                      cltd
   110b4:       f7 39                   idivl  (%rcx)
   110b6:       48 8b 45 f0             mov    -0x10(%rbp),%rax
   110ba:       48 63 ca                movslq %edx,%rcx
   110bd:       8a 14 08                mov    (%rax,%rcx,1),%dl
   110c0:       80 c2 01                add    $0x1,%dl
   110c3:       88 14 08                mov    %dl,(%rax,%rcx,1)
   110c6:       5d                      pop    %rbp
   110c7:       c3                      ret
   110c8:       0f 1f 84 00 00 00 00    nopl   0x0(%rax,%rax,1)
   110cf:       00

This is from Ubuntu/luarocks:

000000000000fc90 <increment_counter>:
    fc90:       80 05 99 4c 04 00 01    addb   $0x1,0x44c99(%rip)        # 54930 <__TMC_END__+0xf8>
    fc97:       48 8b 05 1a 42 04 00    mov    0x4421a(%rip),%rax        # 53eb8 <counters@@Base-0x1d68>
    fc9e:       48 8b 08                mov    (%rax),%rcx
    fca1:       48 85 c9                test   %rcx,%rcx
    fca4:       74 28                   je     fcce <increment_counter+0x3e>
    fca6:       48 8b 05 23 42 04 00    mov    0x44223(%rip),%rax        # 53ed0 <pctable@@Base-0x1d58>
    fcad:       48 83 38 00             cmpq   $0x0,(%rax)
    fcb1:       74 23                   je     fcd6 <increment_counter+0x46>
    fcb3:       80 05 79 4c 04 00 01    addb   $0x1,0x44c79(%rip)        # 54933 <__TMC_END__+0xfb>
    fcba:       48 8b 35 87 42 04 00    mov    0x44287(%rip),%rsi        # 53f48 <max_counters@@Base-0x1cd0>
    fcc1:       89 f8                   mov    %edi,%eax
    fcc3:       99                      cltd
    fcc4:       f7 3e                   idivl  (%rsi)
    fcc6:       48 63 c2                movslq %edx,%rax
    fcc9:       80 04 01 01             addb   $0x1,(%rcx,%rax,1)
    fccd:       c3                      ret
    fcce:       80 05 5c 4c 04 00 01    addb   $0x1,0x44c5c(%rip)        # 54931 <__TMC_END__+0xf9>
    fcd5:       c3                      ret
    fcd6:       80 05 55 4c 04 00 01    addb   $0x1,0x44c55(%rip)        # 54932 <__TMC_END__+0xfa>
    fcdd:       c3                      ret
    fcde:       66 90                   xchg   %ax,%ax

As we can see from disassembly, both times inline 8bit counters are instrumented into code that logically should not cause libfuzzer to get any new features (at least as a side effect).

On average luzer.so produce around 250 parasitic counters. With related PR, I managed to brought it down to 150, and same disassembly now looks like this on debug build under Debian:

0000000000010790 <increment_counter>:
   10790:       55                      push   %rbp
   10791:       48 89 e5                mov    %rsp,%rbp
   10794:       89 7d fc                mov    %edi,-0x4(%rbp)
   10797:       48 8b 05 0a 47 04 00    mov    0x4470a(%rip),%rax        # 54ea8 <counters@@Base-0x1578>
   1079e:       48 83 38 00             cmpq   $0x0,(%rax)
   107a2:       0f 84 3c 00 00 00       je     107e4 <increment_counter+0x54>
   107a8:       48 8b 05 09 47 04 00    mov    0x44709(%rip),%rax        # 54eb8 <pctable@@Base-0x1570>
   107af:       48 83 38 00             cmpq   $0x0,(%rax)
   107b3:       0f 84 2b 00 00 00       je     107e4 <increment_counter+0x54>
   107b9:       48 8b 05 e8 46 04 00    mov    0x446e8(%rip),%rax        # 54ea8 <counters@@Base-0x1578>
   107c0:       48 8b 00                mov    (%rax),%rax
   107c3:       48 89 45 f0             mov    %rax,-0x10(%rbp)
   107c7:       8b 45 fc                mov    -0x4(%rbp),%eax
   107ca:       48 8b 0d 57 47 04 00    mov    0x44757(%rip),%rcx        # 54f28 <max_counters@@Base-0x14f0>
   107d1:       99                      cltd
   107d2:       f7 39                   idivl  (%rcx)
   107d4:       48 8b 45 f0             mov    -0x10(%rbp),%rax
   107d8:       48 63 ca                movslq %edx,%rcx
   107db:       8a 14 08                mov    (%rax,%rcx,1),%dl
   107de:       80 c2 01                add    $0x1,%dl
   107e1:       88 14 08                mov    %dl,(%rax,%rcx,1)
   107e4:       5d                      pop    %rbp
   107e5:       c3                      ret

Segmentation faults on Lua tracing

runner@fv-az2026-24:~/work/luzer/luzer/build$ ctest 
Test project /home/runner/work/luzer/luzer/build
    Start 1: luzer_unit_test
1/5 Test #1: luzer_unit_test ..................   Passed    0.00 sec
    Start 2: luzer_e2e_test
2/5 Test #2: luzer_e2e_test ...................***Exception: SegFault  0.44 sec
    Start 3: luzer_options_test
3/5 Test #3: luzer_options_test ...............   Passed    0.00 sec
    Start 4: luzer_custom_mutator_example
4/5 Test #4: luzer_custom_mutator_example .....***Exception: SegFault  0.09 sec
    Start 5: luzer_basic_example
5/5 Test #5: luzer_basic_example ..............***Not Run (Disabled)   0.00 sec

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.