비교 퍼징 병렬 Rust 도구

Jan 24 2023
나는 이전에 Rust의 "두려움 없는 동시성"을 사용하여 ripunzip이라는 도구를 만드는 방법에 대해 썼습니다. (여기에 몇 가지 성능 결과가 있습니다.)

나는 이전에 Rust의 "두려움 없는 동시성"을 사용하여 ripunzip이라는 도구를 만드는 방법에 대해 썼습니다 . (여기에 몇 가지 성능 결과가 있습니다 .)

병렬이 아닌 일반 압축 해제와 동일한 방식으로 작동하는지 어떻게 확인할 수 있습니까? 예상치 못한 상황에서도?

대답: 비교 퍼징 . Fuzzing은 일반적으로 보안 버그를 찾는 데 사용되는 기술입니다. Rust의 안전하지 않은 코드에서 버그를 찾는 데 사용할 수 있는 방법에 대한 레시피가 있습니다 . 그러나 두 가지 구현이 동일한 방식으로 작동하는지 확인하는 데 사용할 수도 있습니다.

이것은 우리가 기존 도구의 더 빠른 버전을 만들려고 하는 경우에 적합하며 퍼징은 꽤 재미있습니다. 특히 놀라운 arbitrary 크레이트가 있는 Rust에서 그렇습니다 .

계획은 다음과 같습니다.

  • 크레이트를 ripunzip사용하여 zip 파일을 포함하여 에 대한 모든 입력을 설명합니다.arbitrary
  • ripunzip해당 입력을 기반으로 실행
  • 또한 일반 단일 스레드를 사용하여 동일한 파일의 압축을 풉니다.zip-rs
  • 둘 다 성공했는지 또는 둘 다 실패했는지 확인
  • 압축을 푼 디렉터리를 비교합니다. 다르면 충돌!

다음은 . 먼저 입력 데이터를 살펴보겠습니다.


#[derive(arbitrary::Arbitrary, Eq, PartialEq, Hash, Debug, Clone)]
struct ZipMemberFilename(/* details omitted... described later */);

#[derive(Eq, PartialEq, Hash, Debug, Clone, Copy, arbitrary::Arbitrary)]
enum CompressionMethod {
    Stored,
    Deflated,
    Bzip2,
    Zstd,
}

#[derive(arbitrary::Arbitrary, Debug, Clone)]
struct Inputs {
    // HashMap to ensure unique filenames in zip
    zip_members: HashMap<ZipMemberFilename, Vec<u8>>,
    compression_method: CompressionMethod,
    single_threaded: bool,
}

이는 Arbitrary코드가 불투명한 이진 blob에서 이 구조를 구성하기 위해 생성됨을 의미합니다. 이러한 바이너리 Blob은 libfuzzer 에 의해 생성되며 , 결정적으로 커버리지 지침에 따라 가능한 한 많은 프로그램을 점진적으로 탐색하도록 수정 및 재수정됩니다.

HashMap, 벡터 및 사용자 지정 열거형과 같은 꽤 복잡한 입력이 있습니다 . Arbitrary모두 생성할 수 있을 만큼 똑똑합니다.

이제 fuzzer 자체는 본질적으로 사소합니다. 말 그대로 zip을 만들고 압축을 두 번 풀고 출력을 비교하기만 하면 됩니다.

fuzz_target!(|input: Inputs| {
    let progress_reporter = ripunzip::NullProgressReporter;
    let tempdir = tempfile::tempdir().unwrap();
    let output_directory = tempdir.path().join("out_ripunzip");
    let output_directory_unzip = tempdir.path().join("out_unzip");
    std::fs::create_dir_all(&output_directory).unwrap();
    let options = ripunzip::UnzipOptions {
        single_threaded: input.single_threaded,
        output_directory: Some(output_directory.clone()),
    };
    let zipfile = tempdir.path().join("file.zip");
    let mut zip_data = Vec::new();
    create_zip(&mut zip_data, &input.zip_members, input.compression_method);
    let mut file = std::fs::File::create(&zipfile).unwrap();
    file.write_all(&zip_data).unwrap();
    drop(file);
    let file = std::fs::File::open(&zipfile).unwrap();
    let ripunzip_result: Result<(), anyhow::Error> = (|| {
        let ripunzip = ripunzip::UnzipEngine::for_file(file, options, progress_reporter)?;
        ripunzip.unzip()
    })();
    let unziprs_result = unzip_with_zip_rs(&zipfile, &output_directory_unzip);
    match unziprs_result {
        Err(err) => {
            if ripunzip_result.is_ok() {
                panic!("ripunzip succeeded; plain unzip gave {:?}", err)
            }
        }
        Ok(_) => {
            ripunzip_result.unwrap();
            let ripunzip_paths = recursive_lsdir(&output_directory);
            let unzip_paths = recursive_lsdir(&output_directory_unzip);
            // We do not currently compare the actual zip file contents.
            // It seems unlikely that this would be a failure mode where
            // ripunzip would differ from zip-rs.
            assert_eq!(ripunzip_paths, unzip_paths);
        }
    }
});

fn recursive_lsdir(dir: &Path) -> HashSet<std::path::PathBuf> {
    walkdir::WalkDir::new(dir)
        .into_iter()
        .filter_map(|e| e.ok())
        .map(|e| e.path().strip_prefix(dir).unwrap().to_path_buf())
        .collect()
}

// Create a zip file from zip_members into output,
// using the given compression mode. Details omitted.
fn create_zip(output: &mut Vec<u8>, zip_members: &HashMap<ZipMemberFilename, Vec<u8>>, compression_method: CompressionMethod) {
    // ...
}

/// Errors that can occur with a regular zip-rs unzip, details omitted
#[derive(Debug)]
enum ZipRsError {
    // ...
}

/// Unzip the content with standard zip-rs.
fn unzip_with_zip_rs(zipfile_path: &Path, dest_path: &Path) -> Result<(), ZipRsError> {
    // ...
}

#[derive(arbitrary::Arbitrary, Debug, Clone, strum::Display, Hash, Eq, PartialEq)]
enum FilenameSegment {
    Fish,
    A,
    #[strum(serialize = "b")]
    B,
    #[strum(serialize = "31")]
    ThirtyOne,
    #[strum(serialize = "_c")]
    C,
    D,
    #[strum(serialize = "e.txt")]
    ETxt,
}

#[derive(arbitrary::Arbitrary, Eq, PartialEq, Hash, Debug, Clone)]
struct ZipMemberFilename(Vec<FilenameSegment>);

impl Into<String> for &ZipMemberFilename {
    fn into(self) -> String {
        self.0.iter().join("/")
    }
}

이것을 실행하면 어떻게 될까요? fuzzer ferret이 코드베이스 주변을 돌아다니면서 이 유쾌한 출력을 볼 수 있습니다 .

$ cargo +nightly fuzz run fuzz_ripunzip
   Compiling ripunzip v0.2.2 (ripunzip)
   Compiling ripunzip-fuzz v0.0.0 (ripunzip/fuzz)
    Finished release [optimized] target(s) in 18.06s
    Finished release [optimized] target(s) in 0.18s
     Running `target/x86_64-apple-darwin/release/fuzz_ripunzip -artifact_prefix=ripunzip/fuzz/artifacts/fuzz_ripunzip/ ripunzip/fuzz/corpus/fuzz_ripunzip`
fuzz_ripunzip(13490,0x7ff85b1088c0) malloc: nano zone abandoned due to inability to preallocate reserved vm space.
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 3274692728
INFO: Loaded 1 modules   (720556 inline 8-bit counters): 720556 [0x107a95260, 0x107b4510c), 
INFO: Loaded 1 PC tables (720556 PCs): 720556 [0x107b45110,0x108643bd0), 
INFO:        0 files found in ripunzip/fuzz/corpus/fuzz_ripunzip
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 exec/s: 0 rss: 53Mb
 NEW_FUNC[1/171]: 0x105266120 in _$LT$core..iter..adapters..map..Map$LT$I$C$F$GT$$u20$as$u20$core..iter..traits..iterator..Iterator$GT$::fold::h2eed7f9eb6137b14+0x0 (fuzz_ripunzip:x86_64+0x100003120) (BuildId: d85ba98c8ed134a4845c0cff1565ef9632000000200000000100000000000d00)
 NEW_FUNC[2/171]: 0x10526abc0 in _$LT$ripunzip..unzip..cloneable_seekable_reader..CloneableSeekableReader$LT$R$GT$$u20$as$u20$std..io..Read$GT$::read::h7325b227d55c68e7+0x0 (fuzz_ripunzip:x86_64+0x100007bc0) (BuildId: d85ba98c8ed134a4845c0cff1565ef9632000000200000000100000000000d00)
#212 NEW    cov: 1204 ft: 1177 corp: 2/7b lim: 6 exec/s: 212 rss: 59Mb L: 6/6 MS: 4 ChangeBit-ChangeBit-InsertByte-InsertRepeatedBytes-
#213 NEW    cov: 1209 ft: 1182 corp: 3/13b lim: 6 exec/s: 213 rss: 59Mb L: 6/6 MS: 1 ShuffleBytes-
#217 NEW    cov: 1210 ft: 1184 corp: 4/18b lim: 6 exec/s: 217 rss: 59Mb L: 5/6 MS: 4 CopyPart-ChangeByte-ShuffleBytes-InsertRepeatedBytes-
 NEW_FUNC[1/90]: 0x10526a3b0 in _$LT$std..io..cursor..Cursor$LT$$RF$mut$u20$alloc..vec..Vec$LT$u8$C$A$GT$$GT$$u20$as$u20$std..io..Write$GT$::write::hb0a9a4b62999ace6+0x0 (fuzz_ripunzip:x86_64+0x1000073b0) (BuildId: d85ba98c8ed134a4845c0cff1565ef9632000000200000000100000000000d00)
 NEW_FUNC[2/90]: 0x10526ca90 in _$LT$alloc..vec..Vec$LT$T$GT$$u20$as$u20$alloc..vec..spec_from_iter_nested..SpecFromIterNested$LT$T$C$I$GT$$GT$::from_iter::h62629dd53aaca6a9+0x0 (fuzz_ripunzip:x86_64+0x100009a90) (BuildId: d85ba98c8ed134a4845c0cff1565ef9632000000200000000100000000000d00)
#220 NEW    cov: 2100 ft: 2235 corp: 5/23b lim: 6 exec/s: 220 rss: 60Mb L: 5/6 MS: 3 CrossOver-ShuffleBytes-InsertRepeatedBytes-
#222 NEW    cov: 2101 ft: 2237 corp: 6/29b lim: 6 exec/s: 222 rss: 60Mb L: 6/6 MS: 2 CrossOver-CopyPart-
 NEW_FUNC[1/1]: 0x1053ad5c0 in _$LT$alloc..vec..Vec$LT$T$GT$$u20$as$u20$alloc..vec..spec_from_iter_nested..SpecFromIterNested$LT$T$C$I$GT$$GT$::from_iter::h14e3944acd671fa2+0x0 (fuzz_ripunzip:x86_64+0x10014a5c0) (BuildId: d85ba98c8ed134a4845c0cff1565ef9632000000200000000100000000000d00)
#231 NEW    cov: 2108 ft: 2245 corp: 7/35b lim: 6 exec/s: 231 rss: 60Mb L: 6/6 MS: 4 CopyPart-ShuffleBytes-ShuffleBytes-CopyPart-
 NEW_FUNC[1/12]: 0x1052d2580 in core::ptr::drop_in_place$LT$fuzz_ripunzip..ZipRsError$GT$::h864830fa1576e5d5+0x0 (fuzz_ripunzip:x86_64+0x10006f580) (BuildId: d85ba98c8ed134a4845c0cff1565ef9632000000200000000100000000000d00)
 NEW_FUNC[2/12]: 0x1053f7e70 in core::ptr::drop_in_place$LT$anyhow..error..ErrorImpl$LT$anyhow..error..ContextError$LT$core..mem..manually_drop..ManuallyDrop$LT$$RF$str$GT$$C$std..io..error..Error$GT$$GT$$GT$::he14691a68652570b+0x0 (fuzz_ripunzip:x86_64+0x100194e70) (BuildId: d85ba98c8ed134a4845c0cff1565ef9632000000200000000100000000000d00)
#235 NEW    cov: 2193 ft: 2373 corp: 8/41b lim: 6 exec/s: 235 rss: 60Mb L: 6/6 MS: 4 InsertRepeatedBytes-CopyPart-CopyPart-ChangeByte-
#241 REDUCE cov: 2193 ft: 2373 corp: 8/40b lim: 6 exec/s: 241 rss: 61Mb L: 5/6 MS: 1 EraseBytes-
#244 NEW    cov: 2193 ft: 2375 corp: 9/45b lim: 6 exec/s: 244 rss: 61Mb L: 5/6 MS: 3 ChangeByte-EraseBytes-ShuffleBytes-
#252 NEW    cov: 2199 ft: 2394 corp: 10/51b lim: 6 exec/s: 252 rss: 61Mb L: 6/6 MS: 3 CrossOver-InsertByte-InsertRepeatedBytes-
#256 NEW    cov: 2199 ft: 2398 corp: 11/56b lim: 6 exec/s: 256 rss: 61Mb L: 5/6 MS: 4 ChangeBit-CrossOver-CrossOver-InsertRepeatedBytes-
#273 NEW    cov: 2199 ft: 2399 corp: 12/62b lim: 6 exec/s: 273 rss: 62Mb L: 6/6 MS: 2 ChangeBit-InsertByte-
#274 NEW    cov: 2199 ft: 2401 corp: 13/68b lim: 6 exec/s: 274 rss: 62Mb L: 6/6 MS: 1 ChangeByte-
#282 NEW    cov: 2199 ft: 2402 corp: 14/74b lim: 6 exec/s: 282 rss: 62Mb L: 6/6 MS: 3 ShuffleBytes-CrossOver-ChangeBinInt-
#285 NEW    cov: 2205 ft: 2463 corp: 15/80b lim: 6 exec/s: 285 rss: 62Mb L: 6/6 MS: 3 CMP-CopyPart-CMP- DE: " \000\000\000"-"\001\000\000\005"-
#298 NEW    cov: 2205 ft: 2465 corp: 16/86b lim: 6 exec/s: 298 rss: 63Mb L: 6/6 MS: 3 ChangeBit-ChangeBinInt-ChangeBinInt-
 NEW_FUNC[1/1]: 0x1074d09b0 in _$LT$u8$u20$as$u20$arbitrary..Arbitrary$GT$::arbitrary::hbd4728a44a66213a+0x0 (fuzz_ripunzip:x86_64+0x10226d9b0) (BuildId: d85ba98c8ed134a4845c0cff1565ef9632000000200000000100000000000d00)
#314 NEW    cov: 2219 ft: 2479 corp: 17/92b lim: 6 exec/s: 314 rss: 63Mb L: 6/6 MS: 1 ChangeByte-
#340 NEW    cov: 2231 ft: 2499 corp: 18/98b lim: 6 exec/s: 340 rss: 64Mb L: 6/6 MS: 1 ChangeBinInt-
#347 NEW    cov: 2232 ft: 2502 corp: 19/104b lim: 6 exec/s: 347 rss: 64Mb L: 6/6 MS: 2 ChangeBinInt-ChangeBit-
 NEW_FUNC[1/27]: 0x1053a3620 in rayon_core::join::join_context::_$u7b$$u7b$closure$u7d$$u7d$::heeeee28ce9473e59+0x0 (fuzz_ripunzip:x86_64+0x100140620) (BuildId: d85ba98c8ed134a4845c0cff1565ef9632000000200000000100000000000d00)
 NEW_FUNC[2/27]: 0x1053a5d20 in rayon_core::sleep::Sleep::new_jobs::hfc61bcd28f9a7e21+0x0 (fuzz_ripunzip:x86_64+0x100142d20) (BuildId: d85ba98c8ed134a4845c0cff1565ef9632000000200000000100000000000d00)
#379 NEW    cov: 2447 ft: 3413 corp: 20/110b lim: 6 exec/s: 379 rss: 65Mb L: 6/6 MS: 1 ChangeBinInt-
#384 NEW    cov: 2450 ft: 3427 corp: 21/116b lim: 6 exec/s: 384 rss: 65Mb L: 6/6 MS: 5 ChangeByte-CopyPart-ChangeBit-CopyPart-PersAutoDict- DE: "\001\000\000\005"-
 NEW_FUNC[1/1]: 0x105285c50 in std::thread::local::fast::Key$LT$T$GT$::try_initialize::h078871c80893dca2+0x0 (fuzz_ripunzip:x86_64+0x100022c50) (BuildId: d85ba98c8ed134a4845c0cff1565ef9632000000200000000100000000000d00)
#387 NEW    cov: 2469 ft: 3446 corp: 22/122b lim: 6 exec/s: 387 rss: 65Mb L: 6/6 MS: 3 CrossOver-ChangeByte-CrossOver-
#388 NEW    cov: 2470 ft: 3449 corp: 23/128b lim: 6 exec/s: 388 rss: 65Mb L: 6/6 MS: 1 ChangeBinInt-
 NEW_FUNC[1/3]: 0x1053b3ea0 in crossbeam_deque::deque::Worker$LT$T$GT$::pop::h027afe55d57c8358+0x0 (fuzz_ripunzip:x86_64+0x100150ea0) (BuildId: d85ba98c8ed134a4845c0cff1565ef9632000000200000000100000000000d00)
 NEW_FUNC[2/3]: 0x1053b4b30 in crossbeam_deque::deque::Stealer$LT$T$GT$::steal::h20410f4e42e0f324+0x0 (fuzz_ripunzip:x86_64+0x100151b30) (BuildId: d85ba98c8ed134a4845c0cff1565ef9632000000200000000100000000000d00)
#394 NEW    cov: 2497 ft: 3598 corp: 24/134b lim: 6 exec/s: 394 rss: 65Mb L: 6/6 MS: 1 ChangeBit-
#400 NEW    cov: 2497 ft: 3602 corp: 25/140b lim: 6 exec/s: 400 rss: 66Mb L: 6/6 MS: 1 CopyPart-
#411 NEW    cov: 2502 ft: 3618 corp: 26/146b lim: 6 exec/s: 411 rss: 66Mb L: 6/6 MS: 1 InsertByte-
#439 NEW    cov: 2503 ft: 3619 corp: 27/152b lim: 6 exec/s: 439 rss: 67Mb L: 6/6 MS: 3 ChangeBit-ChangeBinInt-ShuffleBytes-
#462 NEW    cov: 2504 ft: 3621 corp: 28/158b lim: 6 exec/s: 462 rss: 68Mb L: 6/6 MS: 3 ChangeBinInt-ShuffleBytes-ShuffleBytes-
#463 NEW    cov: 2504 ft: 3624 corp: 29/164b lim: 6 exec/s: 463 rss: 68Mb L: 6/6 MS: 1 CrossOver-
#464 NEW    cov: 2504 ft: 3630 corp: 30/170b lim: 6 exec/s: 464 rss: 68Mb L: 6/6 MS: 1 ChangeBit-
#480 NEW    cov: 2505 ft: 3631 corp: 31/176b lim: 6 exec/s: 480 rss: 68Mb L: 6/6 MS: 1 CrossOver-
#486 NEW    cov: 2505 ft: 3636 corp: 32/182b lim: 6 exec/s: 486 rss: 68Mb L: 6/6 MS: 1 ChangeBinInt-
#487 NEW    cov: 2505 ft: 3637 corp: 33/188b lim: 6 exec/s: 487 rss: 68Mb L: 6/6 MS: 1 CopyPart-
#527 NEW    cov: 2505 ft: 3641 corp: 34/194b lim: 6 exec/s: 527 rss: 69Mb L: 6/6 MS: 5 ChangeBinInt-CrossOver-CopyPart-ChangeBinInt-PersAutoDict- DE: "\001\000\000\005"-
 NEW_FUNC[1/1]: 0x1052de9a0 in core::iter::traits::double_ended::DoubleEndedIterator::try_rfold::hcf0f30052624299f+0x0 (fuzz_ripunzip:x86_64+0x10007b9a0) (BuildId: d85ba98c8ed134a4845c0cff1565ef9632000000200000000100000000000d00)
#538 NEW    cov: 2535 ft: 3675 corp: 35/200b lim: 6 exec/s: 538 rss: 70Mb L: 6/6 MS: 1 CopyPart-

위 단락을 입력한 후 이제 3795 코드 블록을 탐색합니다.

결국 정체됩니다. 이상하게 매력적입니다.

그래서 효과가 있었나요? 문제가 발견되었나요?

예! 즉시. 예를 들어:

$ RUST_BACKTRACE=1 cargo +nightly fuzz run fuzz_ripunzip
    Finished release [optimized] target(s) in 0.21s
    Finished release [optimized] target(s) in 0.20s
     Running `target/x86_64-apple-darwin/release/fuzz_ripunzip -artifact_prefix=ripunzip/fuzz/artifacts/fuzz_ripunzip/ ripunzip/fuzz/corpus/fuzz_ripunzip`
fuzz_ripunzip(14468,0x7ff85b1088c0) malloc: nano zone abandoned due to inability to preallocate reserved vm space.
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 3659845534
INFO: Loaded 1 modules   (719987 inline 8-bit counters): 719987 [0x10c8e5fe0, 0x10c995c53), 
INFO: Loaded 1 PC tables (719987 PCs): 719987 [0x10c995c58,0x10d492388), 
INFO:        0 files found in ripunzip/fuzz/corpus/fuzz_ripunzip
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 exec/s: 0 rss: 53Mb
WARNING: no interesting inputs were found so far. Is the code instrumented for coverage?
This may also happen if the target rejected all inputs we tried so far
thread '<unnamed>' panicked at 'attempt to subtract with overflow', ripunzip/src/unzip/cloneable_seekable_reader.rs:93:17
stack backtrace:
   0: rust_begin_unwind
             at /rustc/ec56537c4325ce5b798fc3628cbdd48ba4949ae5/library/std/src/panicking.rs:575:5
   1: core::panicking::panic_fmt
             at /rustc/ec56537c4325ce5b798fc3628cbdd48ba4949ae5/library/core/src/panicking.rs:64:14
   2: core::panicking::panic
             at /rustc/ec56537c4325ce5b798fc3628cbdd48ba4949ae5/library/core/src/panicking.rs:111:5
   3: <ripunzip::unzip::cloneable_seekable_reader::CloneableSeekableReader<R> as std::io::Seek>::seek
   4: zip::read::<impl zip::read::zip_archive::ZipArchive<R>>::get_directory_counts
   5: zip::read::<impl zip::read::zip_archive::ZipArchive<R>>::new
   6: ripunzip::unzip::UnzipEngine<P>::for_file
   7: fuzz_ripunzip::_::run
   8: _rust_fuzzer_test_input
   9: std::panicking::try::do_call
  10: ___rust_try
  11: _LLVMFuzzerTestOneInput
  12: __ZN6fuzzer6Fuzzer15ExecuteCallbackEPKhm
  13: __ZN6fuzzer6Fuzzer6RunOneEPKhmbPNS_9InputInfoEbPb
  14: __ZN6fuzzer6Fuzzer16MutateAndTestOneEv
  15: __ZN6fuzzer6Fuzzer4LoopERNSt3__16vectorINS_9SizedFileENS1_9allocatorIS3_EEEE
  16: __ZN6fuzzer12FuzzerDriverEPiPPPcPFiPKhmE
  17: _main
  18: <unknown>
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
==14468== ERROR: libFuzzer: deadly signal
    #0 0x10e2a6185 in __sanitizer_print_stack_trace+0x35 (librustc-nightly_rt.asan.dylib:x86_64h+0x53185) (BuildId: d21cf6fbe4db36c3a2772a5990be16c5240000001000000000070a0000030c00)
    #1 0x10c2c1d1a in fuzzer::PrintStackTrace()+0x2a (fuzz_ripunzip:x86_64+0x102205d1a) (BuildId: 52587ab92ee03de78cc50b187a499a5332000000200000000100000000000d00)
    #2 0x10c2b49e3 in fuzzer::Fuzzer::CrashCallback()+0x43 (fuzz_ripunzip:x86_64+0x1021f89e3) (BuildId: 52587ab92ee03de78cc50b187a499a5332000000200000000100000000000d00)
    #3 0x7ff817802c1c in _sigtramp+0x1c (libsystem_platform.dylib:x86_64+0x3c1c) (BuildId: f314b62b98f43a7c82968739f8b6855a240000001000000000010d0000010d00)

NOTE: libFuzzer has rudimentary signal handlers.
      Combine libFuzzer with AddressSanitizer or similar for better crash reports.
SUMMARY: libFuzzer: deadly signal
MS: 1 InsertRepeatedBytes-; base unit: adc83b19e793491b1c6ea0fd8b46cd9f32e592fc
0xa,0x0,0x0,0x0,0x0,0x0,
\012\000\000\000\000\000
artifact_prefix='ripunzip/fuzz/artifacts/fuzz_ripunzip/'; Test unit written to ripunzip/fuzz/artifacts/fuzz_ripunzip/crash-fd324ba7ec17e3df5e8735319dc70009a81c1b6c
Base64: CgAAAAAA

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

Failing input:

 artifacts/fuzz_ripunzip/crash-fd324ba7ec17e3df5e8735319dc70009a81c1b6c

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

 Inputs {
     zip_members: {},
     compression_method: Stored,
     single_threaded: false,
 }

Reproduce with:

 cargo fuzz run fuzz_ripunzip artifacts/fuzz_ripunzip/crash-fd324ba7ec17e3df5e8735319dc70009a81c1b6c

Minimize test case with:

 cargo fuzz tmin fuzz_ripunzip artifacts/fuzz_ripunzip/crash-fd324ba7ec17e3df5e8735319dc70009a81c1b6c

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

Error: Fuzz target exited with exit status: 77

Stack backtrace:
   0: std::backtrace::Backtrace::create
   1: std::backtrace::Backtrace::capture
   2: anyhow::error::<impl anyhow::Error>::msg
   3: cargo_fuzz::project::FuzzProject::exec_fuzz
   4: <cargo_fuzz::options::run::Run as cargo_fuzz::RunCommand>::run_command
   5: cargo_fuzz::main
   6: std::sys_common::backtrace::__rust_begin_short_backtrace
   7: std::rt::lang_start::{{closure}}
   8: std::rt::lang_start_internal
   9: _main
  10: <unknown>

그것은 또한 다음을 발견했습니다.

  • 때때로 여러 스레드가 압축을 풀고 있던 구성원의 상위 디렉토리를 만들기 위해 경쟁했습니다.
  • 우리는 다음으로 끝나는 파일 이름에 대해 다른 결정을 내렸습니다 /— 저는 여기에서 zip-rs 동작에 맞췄습니다.

추신 : 이제 4359 코드 블록을 탐색했습니다.