Skip to content

Adding support of libFuzzer - #3506

Draft
alexveden wants to merge 2 commits into
c3lang:masterfrom
alexveden:master
Draft

Adding support of libFuzzer#3506
alexveden wants to merge 2 commits into
c3lang:masterfrom
alexveden:master

Conversation

@alexveden

Copy link
Copy Markdown
Contributor

Hi, I'd like to post throaway POC PR for demonstrating fuzzing capabilities. Currently I added it in Linux and MacOS (untested!). This PR is backing for #3505 proposal. It's made with AI support, take is with grain of salt. I'm open for criticism.

The escence of this PR is in small addition in the wrapper/src/wrapper.cpp.

This is sample C3 fuzzing program:

module fuzz_target;

extern fn void abort() @cname("abort");

// Called by libFuzzer for every input. Returns 0 on success; a crash or
// abort() reports a finding.
fn int llvm_fuzzer_test_one_input(char* data, usz size) @export("LLVMFuzzerTestOneInput")
{
    // Pretend protocol: [0..2] = "GET", [3] = '/', [4] = body length,
    // [5..] = body bytes. A body shorter than the declared length is a bug.
    if (size < 5) return 0;
    if (data[0] != 'G') return 0;
    if (data[1] != 'E') return 0;
    if (data[2] != 'T') return 0;
    if (data[3] != '/') return 0;
    usz len = (usz)data[4];
    if (size >= 5 + len) return 0; // body complete: input is fine.
    // Deliberate bug: truncated body accepted. In real code this would be
    // an out-of-bounds read; here it is simulated with abort() so the fuzzer
    // run terminates with a reportable crash.
    abort();
    return 0;
}

Run fuzzer with:

build/c3c compile --sanitize=fuzzer --no-entry fuzz_target.c3 -o fuzz
./fuzz

Fuzzer output on Linux:

INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 2053795620
INFO: Loaded 1 modules   (5530 inline 8-bit counters): 5530 [0x55b5c1aee6d0, 0x55b5c1aefc6a),
INFO: Loaded 1 PC tables (5530 PCs): 5530 [0x55b5c1aefc70,0x55b5c1b05610),
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: 2 ft: 2 corp: 1/1b exec/s: 0 rss: 28Mb
#203    NEW    cov: 3 ft: 3 corp: 2/7b lim: 6 exec/s: 0 rss: 28Mb L: 6/6 MS: 1 InsertRepeatedBytes-
#210    REDUCE cov: 3 ft: 3 corp: 2/6b lim: 6 exec/s: 0 rss: 28Mb L: 5/5 MS: 2 ShuffleBytes-EraseBytes-
#18476  REDUCE cov: 4 ft: 4 corp: 3/11b lim: 184 exec/s: 0 rss: 28Mb L: 5/5 MS: 1 ChangeByte-
#37889  NEW    cov: 5 ft: 5 corp: 4/17b lim: 373 exec/s: 0 rss: 28Mb L: 6/6 MS: 3 ShuffleBytes-ChangeByte-InsertByte-
#38020  NEW    cov: 6 ft: 6 corp: 5/94b lim: 373 exec/s: 0 rss: 28Mb L: 77/77 MS: 1 InsertRepeatedBytes-
#38066  REDUCE cov: 6 ft: 6 corp: 5/93b lim: 373 exec/s: 0 rss: 28Mb L: 5/77 MS: 1 EraseBytes-
#38213  REDUCE cov: 6 ft: 6 corp: 5/60b lim: 373 exec/s: 0 rss: 28Mb L: 44/44 MS: 2 CopyPart-EraseBytes-
#38283  REDUCE cov: 6 ft: 6 corp: 5/43b lim: 373 exec/s: 0 rss: 28Mb L: 27/27 MS: 5 CrossOver-ChangeByte-ChangeByte-ChangeBit-EraseBytes-
#38579  REDUCE cov: 6 ft: 6 corp: 5/36b lim: 373 exec/s: 0 rss: 28Mb L: 20/20 MS: 1 EraseBytes-
#38651  REDUCE cov: 6 ft: 6 corp: 5/34b lim: 373 exec/s: 0 rss: 28Mb L: 18/18 MS: 2 ChangeBit-EraseBytes-
#38799  REDUCE cov: 6 ft: 6 corp: 5/33b lim: 373 exec/s: 0 rss: 28Mb L: 17/17 MS: 3 CopyPart-InsertByte-EraseBytes-
#39003  REDUCE cov: 6 ft: 6 corp: 5/32b lim: 373 exec/s: 0 rss: 28Mb L: 16/16 MS: 4 ChangeBinInt-ShuffleBytes-CrossOver-EraseBytes-
#39035  REDUCE cov: 6 ft: 6 corp: 5/31b lim: 373 exec/s: 0 rss: 28Mb L: 15/15 MS: 2 InsertByte-EraseBytes-
#39057  REDUCE cov: 6 ft: 6 corp: 5/27b lim: 373 exec/s: 0 rss: 28Mb L: 11/11 MS: 2 ShuffleBytes-EraseBytes-
#39071  REDUCE cov: 6 ft: 6 corp: 5/23b lim: 373 exec/s: 0 rss: 28Mb L: 7/7 MS: 4 ChangeBit-ChangeByte-ChangeByte-EraseBytes-
#39150  REDUCE cov: 6 ft: 6 corp: 5/21b lim: 373 exec/s: 0 rss: 28Mb L: 5/5 MS: 4 InsertByte-InsertByte-InsertByte-CrossOver-
==1241518== ERROR: libFuzzer: deadly signal
    #0 0x55b5c1a2e5b8 in __sanitizer_print_stack_trace (/home/ubertrader/code/c3c/fuzz+0x975b8) (BuildId: 6e468bf54b605a9d36c1dfe5e255726aff893ca6)
    #1 0x55b5c1a0118c in fuzzer::PrintStackTrace() (/home/ubertrader/code/c3c/fuzz+0x6a18c) (BuildId: 6e468bf54b605a9d36c1dfe5e255726aff893ca6)
    #2 0x55b5c19e6107 in fuzzer::Fuzzer::CrashCallback() (/home/ubertrader/code/c3c/fuzz+0x4f107) (BuildId: 6e468bf54b605a9d36c1dfe5e255726aff893ca6)
    #3 0x7f75d544bdef  (/lib/x86_64-linux-gnu/libc.so.6+0x3fdef) (BuildId: c495b62edadd6c356265942ec1282d98058a7b41)
    #4 0x7f75d54a095b in __pthread_kill_implementation nptl/pthread_kill.c:43:17
    #5 0x7f75d544bcc1 in raise signal/../sysdeps/posix/raise.c:26:13
    #6 0x7f75d54344ab in abort stdlib/abort.c:77:3
    #7 0x55b5c1abec2f in LLVMFuzzerTestOneInput /home/ubertrader/code/c3c/scripts/tools/fuzz_target.c3:41:5
    #8 0x55b5c19e780a in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/home/ubertrader/code/c3c/fuzz+0x5080a) (BuildId: 6e468bf54b605a9d36c1dfe5e255726aff893ca6)
    #9 0x55b5c19e6e19 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) (/home/ubertrader/code/c3c/fuzz+0x4fe19) (BuildId: 6e468bf54b605a9d36c1dfe5e255726aff893ca6)
    #10 0x55b5c19e88e5 in fuzzer::Fuzzer::MutateAndTestOne() (/home/ubertrader/code/c3c/fuzz+0x518e5) (BuildId: 6e468bf54b605a9d36c1dfe5e255726aff893ca6)
    #11 0x55b5c19e93d5 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, std::allocator<fuzzer::SizedFile>>&) (/home/ubertrader/code/c3c/fuzz+0x523d5) (BuildId: 6e468bf54b605a9d36c1dfe5e255726aff893ca6)
    #12 0x55b5c19d5995 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/ubertrader/code/c3c/fuzz+0x3e995) (BuildId: 6e468bf54b605a9d36c1dfe5e255726aff893ca6)
    #13 0x55b5c1a01cf6 in main (/home/ubertrader/code/c3c/fuzz+0x6acf6) (BuildId: 6e468bf54b605a9d36c1dfe5e255726aff893ca6)
    #14 0x7f75d5435ca7 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
    #15 0x7f75d5435d64 in __libc_start_main csu/../csu/libc-start.c:360:3
    #16 0x55b5c19c9cf0 in _start (/home/ubertrader/code/c3c/fuzz+0x32cf0) (BuildId: 6e468bf54b605a9d36c1dfe5e255726aff893ca6)

NOTE: libFuzzer has rudimentary signal handlers.
      Combine libFuzzer with AddressSanitizer or similar for better crash reports.
SUMMARY: libFuzzer: deadly signal
MS: 2 CrossOver-InsertByte-; base unit: d2481f848d163d7661d70867e8d2bb73d151dbda
0x47,0x45,0x54,0x2f,0x40,0x61,0x47,0x63,0xa,0x63,0x63,
GET/@aGc\012cc
artifact_prefix='./'; Test unit written to ./crash-ec416b85430932ebfbea63fb7010a99092e25976
Base64: R0VUL0BhR2MKY2M=

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant