coreutils icon indicating copy to clipboard operation
coreutils copied to clipboard

Fuzz date is quickly identifying errors

Open qarmin opened this issue 3 years ago • 10 comments

When I tried to use with this patch a fuzzer:

Then after first fuzzer(https://github.com/rust-fuzz/cargo-fuzz) run(with any value, since input is always same)

cd src/uu/date
cargo +nightly fuzz run fuzz_target_1

I got this memory leak;

Direct leak of 182 byte(s) in 1 object(s) allocated from:
   #0 0x55bee9d209c6 in __interceptor_realloc /rustc/llvm/src/llvm-project/compiler-rt/lib/asan/asan_malloc_linux.cpp:85:3
   #1 0x55bee9e3d286 in alloc::raw_vec::RawVec$LT$T$C$A$GT$::shrink::h0cbb59626d49af4c (/home/rafal/test/coreutils/src/uu/date/fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1+0x66f286) (BuildId: 71e645d4db0079b28c3f9b4da7eb5ca63f0a5eee)
   #2 0x55bee9e780ec in uucore::format_usage::h4aeffd44ee9d338a (/home/rafal/test/coreutils/src/uu/date/fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1+0x6aa0ec) (BuildId: 71e645d4db0079b28c3f9b4da7eb5ca63f0a5eee)
   #3 0x55bee9dd442a in uu_date::uu_app::h74bd79f63f3d4e41 (/home/rafal/test/coreutils/src/uu/date/fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1+0x60642a) (BuildId: 71e645d4db0079b28c3f9b4da7eb5ca63f0a5eee)
   #4 0x55bee9da1f9f in uu_date::uumain::uumain::he8b051ec18eef25a (/home/rafal/test/coreutils/src/uu/date/fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1+0x5d3f9f) (BuildId: 71e645d4db0079b28c3f9b4da7eb5ca63f0a5eee)
   #5 0x55bee9da0bb4 in uu_date::uumain::h612725504c625df4 (/home/rafal/test/coreutils/src/uu/date/fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1+0x5d2bb4) (BuildId: 71e645d4db0079b28c3f9b4da7eb5ca63f0a5eee)
   #6 0x55bee9db41d4 in rust_fuzzer_test_input (/home/rafal/test/coreutils/src/uu/date/fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1+0x5e61d4) (BuildId: 71e645d4db0079b28c3f9b4da7eb5ca63f0a5eee)
   #7 0x55beea5f3728 in __rust_try libfuzzer_sys.3c47a7c2-cgu.0
   #8 0x55beea5f2ac8 in LLVMFuzzerTestOneInput (/home/rafal/test/coreutils/src/uu/date/fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1+0xe24ac8) (BuildId: 71e645d4db0079b28c3f9b4da7eb5ca63f0a5eee)
   #9 0x55beea5f9ef5 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) (/home/rafal/test/coreutils/src/uu/date/fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1+0xe2bef5) (BuildId: 71e645d4db0079b28c3f9b4da7eb5ca63f0a5eee)
   #10 0x55beea5ff7a3 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool, bool*) (/home/rafal/test/coreutils/src/uu/date/fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1+0xe317a3) (BuildId: 71e645d4db0079b28c3f9b4da7eb5ca63f0a5eee)
   #11 0x55beea6027bb in fuzzer::Fuzzer::ReadAndExecuteSeedCorpora(std::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) (/home/rafal/test/coreutils/src/uu/date/fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1+0xe347bb) (BuildId: 71e645d4db0079b28c3f9b4da7eb5ca63f0a5eee)
   #12 0x55beea602997 in fuzzer::Fuzzer::Loop(std::vector<fuzzer::SizedFile, fuzzer::fuzzer_allocator<fuzzer::SizedFile> >&) (/home/rafal/test/coreutils/src/uu/date/fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1+0xe34997) (BuildId: 71e645d4db0079b28c3f9b4da7eb5ca63f0a5eee)
   #13 0x55beea610f70 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) (/home/rafal/test/coreutils/src/uu/date/fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1+0xe42f70) (BuildId: 71e645d4db0079b28c3f9b4da7eb5ca63f0a5eee)
   #14 0x55bee9c9f206 in main (/home/rafal/test/coreutils/src/uu/date/fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1+0x4d1206) (BuildId: 71e645d4db0079b28c3f9b4da7eb5ca63f0a5eee)
   #15 0x7fba56b14d8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16

I'm not sure if this is a problem with fuzzer or date

qarmin avatar Aug 06 '22 19:08 qarmin

Cool that you are fuzzing it! Do you have the input that make date break? thanks

sylvestre avatar Aug 06 '22 20:08 sylvestre

I haven't tried to use real values from fuzzer because I have a problem even with static and almost empty input(since I didn't use uutils earlier I could done something wrong, so I want to fix or workaround this issue)

use libfuzzer_sys::fuzz_target;

use uu_date::uumain;
use std::ffi::OsString;

fuzz_target!(|data: &[u8]| {
    let iter: Vec<OsString> = [""].into_iter().map(|e|OsString::from(e)).collect();
    let it2 = iter.into_iter();
       uumain(it2);

});

qarmin avatar Aug 06 '22 20:08 qarmin

The offending function seems to be this: https://github.com/uutils/coreutils/blob/main/src/uucore/src/lib/lib.rs#L104

Which indeed intentionally leaks memory to create a &'static str from a boxed string. A more sophisticated method would be nice, but I don't think this leak is problematic, because it's called only once per invocation.

tertsdiepraam avatar Aug 06 '22 22:08 tertsdiepraam

@qarmin could you please suppress this leak and try again? I am curious :)

sylvestre avatar Aug 14 '22 19:08 sylvestre

I only tested date tool, because this it is tool with multiple options which is safe to use(not move any files etc.) - I was able to easily reproduce this issue in less than second of running fuzzer - https://github.com/uutils/coreutils/issues/3780

fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1: invalid date $'k+Skk\x07\x00'
fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1: invalid date $'k+\x1F'$'2\x01Sk0k\x07'
2022-08-14T21:27:33.047797994+02:00	%%)
		%%)
thread '<unnamed>' panicked at 'a Display implementation returned an error unexpectedly: Error', /rustc/20ffea6938b5839c390252e07940b99e3b6a889a/library/alloc/src/string.rs:2490:14
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
==20141== ERROR: libFuzzer: deadly signal
    #0 0x55f590eb0301 in __sanitizer_print_stack_trace /rustc/llvm/src/llvm-project/compiler-rt/lib/asan/asan_stack.cpp:87:3
    #1 0x55f59179263e in fuzzer::PrintStackTrace() (/home/rafal/test/coreutils/src/uu/date/fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1+0xe3a63e) (BuildId: fe48eaa4769aead65a31c2a871d82a481322ec0f)
    #2 0x55f5917762b9 in fuzzer::Fuzzer::CrashCallback() (/home/rafal/test/coreutils/src/uu/date/fuzz/target/x86_64-unknown-linux-gnu/release/fuzz_target_1+0xe1e2b9) (BuildId: fe48eaa4769aead65a31c2a871d82a481322ec0f)
    ...
    ...
    ...
 NOTE: libFuzzer has rudimentary signal handlers.
      Combine libFuzzer with AddressSanitizer or similar for better crash reports.
SUMMARY: libFuzzer: deadly signal
MS: 3 ChangeBinInt-CrossOver-InsertByte-; base unit: 8f3f38482d6a03ddd64ed1ccbc4cabf8d8ebe506
0x2b,0x1f,0x9,0x9,0x25,0x25,0x25,0x5b,0x25,0x29,
+\x1f\x09\x09%%%[%)
artifact_prefix='/home/rafal/test/coreutils/src/uu/date/fuzz/artifacts/fuzz_target_1/'; Test unit written to /home/rafal/test/coreutils/src/uu/date/fuzz/artifacts/fuzz_target_1/crash-b4639e53c4cc3f6cd15c1cf0612afa385c206572
Base64: Kx8JCSUlJVslKQ==

────────────────────────────────────────────────────────────────────────────────

Failing input:

	fuzz/artifacts/fuzz_target_1/crash-b4639e53c4cc3f6cd15c1cf0612afa385c206572

Output of `std::fmt::Debug`:

	[43, 31, 9, 9, 37, 37, 37, 91, 37, 41]

Steps to reproduce patch.txt

cargo install cargo-fuzz
git apply patch.txt # patch from above
cd /src/uu/date
cargo +nightly fuzz run fuzz_target_1 -- -detect_leaks=0

qarmin avatar Aug 14 '22 19:08 qarmin

Very cool stuff. Once it doesn't break after a few seconds, I would like to have this into the CI :)

sylvestre avatar Aug 14 '22 19:08 sylvestre

Good news! Using clap 4, I've been able to remove the leak.

tertsdiepraam avatar Oct 13 '22 15:10 tertsdiepraam

Nice, I didn't realize that it could be fixed by clap

sylvestre avatar Oct 13 '22 15:10 sylvestre

I originally wrote that function because I needed a string that lived as long as a clap::Command so that I could pass it into Command::override_usage, but now override_usage can also take a String, so we no longer need to worry about the lifetime.

tertsdiepraam avatar Oct 13 '22 16:10 tertsdiepraam

With #4244 I was able to run the fuzzer for ~ 1hour without crashes.

jaggededgedjustice avatar Dec 29 '22 21:12 jaggededgedjustice

Closing this ticket because fuzzing of date has been added to the CICD in the meantime.

cakebaker avatar Apr 30 '23 14:04 cakebaker