Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  test_minidump.rs   Sprache: unbekannt

 
// Copyright 2015 Ted Mielczarek. See the COPYRIGHT
// file at the top-level directory of this distribution.

use debugid::{CodeId, DebugId};
use minidump::system_info::{Cpu, Os};
use minidump::*;
use minidump_common::format as md;
use num_traits::cast::FromPrimitive;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;
use std::time::SystemTime;

fn get_test_minidump_path(filename: &str) -> PathBuf {
    let mut path = PathBuf::from(file!());
    path.pop();
    path.pop();
    path.pop();
    path.push("../");
    path.push("testdata");
    path.push(filename);
    println!("{path:?}");
    path
}

fn read_test_minidump() -> Result<MmapMinidump, Error> {
    let path = get_test_minidump_path("test.dmp");
    Minidump::read_path(path)
}

fn read_linux_minidump() -> Result<MmapMinidump, Error> {
    let path = get_test_minidump_path("linux-mini.dmp");
    Minidump::read_path(path)
}

#[ctor::ctor]
fn init_logger() {
    env_logger::builder().is_test(true).init();
}

#[test]
fn test_minidump_read_path() {
    read_test_minidump().unwrap();
}

#[test]
fn test_minidump_read() {
    let path = get_test_minidump_path("test.dmp");
    let mut f = File::open(path).unwrap();
    let mut buf = vec![];
    f.read_to_end(&mut buf).unwrap();
    let _dump = Minidump::read(buf).unwrap();
}

#[test]
fn test_module_list() {
    let dump = read_test_minidump().unwrap();
    let module_list = dump.get_stream::<MinidumpModuleList>().unwrap();
    assert_eq!(
        module_list.module_at_address(0x400000).unwrap().code_file(),
        "c:\\test_app.exe"
    );
    let modules = module_list.iter().collect::<Vec<_>>();
    let module_files = modules.iter().map(|m| m.code_file()).collect::<Vec<_>>();
    assert_eq!(modules.len(), 13);
    assert_eq!(modules[0].base_address(), 0x400000);
    assert_eq!(modules[0].size(), 0x2d000);
    assert_eq!(modules[0].code_file(), "c:\\test_app.exe");
    assert_eq!(
        modules[0].code_identifier().unwrap(),
        CodeId::new("45D35F6C2d000".to_string())
    );
    assert_eq!(modules[0].debug_file().unwrap(), "c:\\test_app.pdb");
    assert_eq!(
        modules[0].debug_identifier().unwrap(),
        DebugId::from_breakpad("5A9832E5287241C1838ED98914E9B7FF1").unwrap()
    );
    assert!(modules[0].version().is_none());

    assert_eq!(modules[12].base_address(), 0x76bf0000);
    assert_eq!(modules[12].size(), 0xb000);
    assert_eq!(modules[12].code_file(), "C:\\WINDOWS\\system32\\psapi.dll");
    assert_eq!(
        modules[12].code_identifier().unwrap(),
        CodeId::new("411096CAb000".to_string())
    );
    assert_eq!(modules[12].debug_file().unwrap(), "psapi.pdb");
    assert_eq!(
        modules[12].debug_identifier().unwrap(),
        DebugId::from_breakpad("A5C3A1F9689F43D8AD228A09293889702").unwrap()
    );
    assert_eq!(modules[12].version().unwrap(), "5.1.2600.2180");

    assert_eq!(
        module_files,
        vec![
            r"c:\test_app.exe",
            r"C:\WINDOWS\system32\ntdll.dll",
            r"C:\WINDOWS\system32\kernel32.dll",
            r"C:\WINDOWS\system32\ole32.dll",
            r"C:\WINDOWS\system32\advapi32.dll",
            r"C:\WINDOWS\system32\rpcrt4.dll",
            r"C:\WINDOWS\system32\gdi32.dll",
            r"C:\WINDOWS\system32\user32.dll",
            r"C:\WINDOWS\system32\msvcrt.dll",
            r"C:\WINDOWS\system32\imm32.dll",
            r"C:\WINDOWS\system32\dbghelp.dll",
            r"C:\WINDOWS\system32\version.dll",
            r"C:\WINDOWS\system32\psapi.dll",
        ]
    );

    assert_eq!(
        module_list
            .by_addr()
            .map(|m| m.code_file())
            .collect::<Vec<_>>(),
        vec![
            r"c:\test_app.exe",
            r"C:\WINDOWS\system32\dbghelp.dll",
            r"C:\WINDOWS\system32\imm32.dll",
            r"C:\WINDOWS\system32\psapi.dll",
            r"C:\WINDOWS\system32\ole32.dll",
            r"C:\WINDOWS\system32\version.dll",
            r"C:\WINDOWS\system32\msvcrt.dll",
            r"C:\WINDOWS\system32\user32.dll",
            r"C:\WINDOWS\system32\advapi32.dll",
            r"C:\WINDOWS\system32\rpcrt4.dll",
            r"C:\WINDOWS\system32\gdi32.dll",
            r"C:\WINDOWS\system32\kernel32.dll",
            r"C:\WINDOWS\system32\ntdll.dll",
        ]
    );
}

#[test]
fn test_system_info() {
    let dump = read_test_minidump().unwrap();
    let system_info = dump.get_stream::<MinidumpSystemInfo>().unwrap();
    assert_eq!(system_info.os, Os::Windows);
    assert_eq!(system_info.cpu, Cpu::X86);
    assert_eq!(
        system_info.cpu_info().unwrap(),
        "GenuineIntel family 6 model 13 stepping 8"
    );
    assert_eq!(&system_info.csd_version().unwrap(), "Service Pack 2");
}

#[test]
fn test_misc_info() {
    let dump = read_test_minidump().unwrap();
    let misc_info = dump.get_stream::<MinidumpMiscInfo>().unwrap();
    assert_eq!(misc_info.raw.process_id(), Some(&3932));
    assert_eq!(misc_info.raw.process_create_time(), Some(&0x45d35f73));
    assert_eq!(
        misc_info
            .process_create_time()
            .unwrap()
            .duration_since(SystemTime::UNIX_EPOCH)
            .unwrap()
            .as_secs(),
        1171480435, // = 2007-02-14T19:13:55
    );
}

#[test]
fn test_breakpad_info() {
    let dump = read_test_minidump().unwrap();
    let breakpad_info = dump.get_stream::<MinidumpBreakpadInfo>().unwrap();
    assert_eq!(breakpad_info.dump_thread_id.unwrap(), 0x11c0);
    assert_eq!(breakpad_info.requesting_thread_id.unwrap(), 0xbf4);
}

#[test]
fn test_crashpad_info() {
    let path = get_test_minidump_path("simple-crashpad.dmp");
    let dump = Minidump::read_path(&path).unwrap();
    let crashpad_info = dump.get_stream::<MinidumpCrashpadInfo>().unwrap();

    let report_id = md::GUID {
        data1: 0x42F9_DE72,
        data2: 0x518A,
        data3: 0x43DD,
        data4: [0x97, 0xD7, 0x8D, 0xDC, 0x32, 0x8D, 0x36, 0x62],
    };
    assert_eq!(crashpad_info.raw.report_id, report_id);

    let client_id = md::GUID {
        data1: 0x6FD2_B3B9,
        data2: 0x9833,
        data3: 0x4B2F,
        data4: [0xBB, 0xF7, 0xB, 0xCF, 0x50, 0x1B, 0xAD, 0x7E],
    };
    assert_eq!(crashpad_info.raw.client_id, client_id);

    assert_eq!(crashpad_info.simple_annotations["hello"], "world");
    assert_eq!(crashpad_info.module_list.len(), 2);

    let module = &crashpad_info.module_list[0];
    assert_eq!(module.module_index, 16);
    assert_eq!(module.list_annotations, vec!["abort() called".to_owned()]);
    assert!(module.simple_annotations.is_empty());
    assert!(module.annotation_objects.is_empty());
}

#[test]
fn test_assertion() {
    let path = get_test_minidump_path("invalid-parameter.dmp");
    let dump = Minidump::read_path(&path).unwrap();
    let assertion = dump.get_stream::<MinidumpAssertion>().unwrap();
    assert_eq!(assertion.expression().unwrap(), "format != nullptr");
    assert_eq!(assertion.function().unwrap(), "common_vfprintf");
    assert_eq!(
        assertion.file().unwrap(),
        r"minkernel\crts\ucrt\src\appcrt\stdio\output.cpp"
    );
    assert_eq!(assertion.raw.line, 32);
    assert_eq!(
        md::AssertionType::from_u32(assertion.raw._type),
        Some(md::AssertionType::InvalidParameter)
    );
}

#[test]
fn test_exception() {
    let dump = read_test_minidump().unwrap();
    let exception = dump.get_stream::<MinidumpException>().unwrap();
    let system_info = dump.get_stream::<MinidumpSystemInfo>().unwrap();
    let misc_info = dump.get_stream::<MinidumpMiscInfo>().ok();
    assert_eq!(exception.thread_id, 0xbf4);
    assert_eq!(exception.raw.exception_record.exception_code, 0xc0000005);
    if let Some(ctx) = exception
        .context(&system_info, misc_info.as_ref())
        .as_deref()
    {
        assert_eq!(ctx.get_instruction_pointer(), 0x40429e);
        assert_eq!(ctx.get_stack_pointer(), 0x12fe84);
        if let MinidumpContext {
            raw: MinidumpRawContext::X86(ref raw),
            ref valid,
        } = *ctx
        {
            assert_eq!(raw.eip, 0x40429e);
            assert_eq!(*valid, MinidumpContextValidity::All);
        } else {
            panic!("Wrong context type");
        }
    } else {
        panic!("Missing context");
    }
}

#[test]
fn test_thread_list() {
    let dump = read_test_minidump().unwrap();
    let thread_list = dump.get_stream::<MinidumpThreadList<'_>>().unwrap();
    let system_info = dump.get_stream::<MinidumpSystemInfo>().unwrap();
    let misc_info = dump.get_stream::<MinidumpMiscInfo>().ok();
    let memory_list = dump.get_memory().unwrap_or_default();

    let threads = &thread_list.threads;
    assert_eq!(threads.len(), 2);
    assert_eq!(threads[0].raw.thread_id, 0xbf4);
    assert_eq!(threads[1].raw.thread_id, 0x11c0);
    let id = threads[1].raw.thread_id;
    assert_eq!(thread_list.get_thread(id).unwrap().raw.thread_id, id);
    if let Some(ctx) = threads[0]
        .context(&system_info, misc_info.as_ref())
        .as_deref()
    {
        assert_eq!(ctx.get_instruction_pointer(), 0x7c90eb94);
        assert_eq!(ctx.get_stack_pointer(), 0x12f320);
        if let MinidumpContext {
            raw: MinidumpRawContext::X86(ref raw),
            ref valid,
        } = *ctx
        {
            assert_eq!(raw.eip, 0x7c90eb94);
            assert_eq!(*valid, MinidumpContextValidity::All);
        } else {
            panic!("Wrong context type");
        }
    } else {
        panic!("Missing context");
    }
    if let Some(ref stack) = threads[0].stack_memory(&memory_list) {
        // Try the beginning
        assert_eq!(stack.get_memory_at_address::<u8>(0x12f31c).unwrap(), 0);
        assert_eq!(stack.get_memory_at_address::<u16>(0x12f31c).unwrap(), 0);
        assert_eq!(stack.get_memory_at_address::<u32>(0x12f31c).unwrap(), 0);
        assert_eq!(
            stack.get_memory_at_address::<u64>(0x12f31c).unwrap(),
            0x7c90e9c000000000
        );
        // And the end
        assert_eq!(stack.get_memory_at_address::<u8>(0x12ffff).unwrap(), 0);
        assert_eq!(stack.get_memory_at_address::<u16>(0x12fffe).unwrap(), 0);
        assert_eq!(stack.get_memory_at_address::<u32>(0x12fffc).unwrap(), 0);
        assert_eq!(
            stack.get_memory_at_address::<u64>(0x12fff8).unwrap(),
            0x405443
        );
    } else {
        panic!("Missing stack memory");
    }
}

#[test]
fn test_empty_minidump() {
    match Minidump::read(&b""[..]) {
        Ok(_) => panic!("Should have failed to read minidump"),
        Err(e) => assert_eq!(e, Error::MissingHeader),
    }
}

#[test]
fn backwards_range() {
    let data = include_bytes!("../../testdata/invalid-range.dmp");

    match Minidump::read(&data[..]) {
        Ok(f) => {
            // TODO verify this is correct
            // This seems to call `MinidumpStream::read()` with a `bytes` that is the entire
            // minidump!
            let _ = f
                .get_stream::<MinidumpLinuxMaps>()
                .expect_err("range should be invalid");
        }
        Err(e) => {
            panic!("Expected to parse the header, got {:?}", e);
        }
    }
}

#[test]
fn test_record_count_mac_info() {
    let data = include_bytes!("../../testdata/invalid-record-count.dmp");

    match Minidump::read(&data[..]) {
        Ok(f) => {
            let _ = f.get_stream::<MinidumpMacCrashInfo>();
        }
        Err(e) => {
            panic!("Expected to parse the header, got {:?}", e);
        }
    }
}

#[test]
fn test_linux_os_version() {
    let dump = read_linux_minidump().unwrap();
    let system_info = dump.get_stream::<MinidumpSystemInfo>().unwrap();

    assert_eq!(system_info.os_parts().0, "4.9.60-linuxkit-aufs");
    assert_eq!(
        system_info.os_parts().1.unwrap(),
        "#1 SMP Mon Nov 6 16:00:12 UTC 2017",
    );
}

#[test]
fn test_full_dump_memory() {
    let path = get_test_minidump_path("full-dump.dmp");
    let dump = Minidump::read_path(&path).unwrap();
    let memory_list = dump.get_stream::<MinidumpMemory64List<'_>>().unwrap();
    assert_eq!(memory_list.iter().count(), 54);
    let blocks: Vec<_> = memory_list.iter().take(3).collect();
    assert_eq!(blocks[0].base_address, 0x007FFE0000);
    assert_eq!(blocks[0].size, 0x1000);
    assert_eq!(blocks[0].bytes[0..8], [0, 0, 0, 0, 0, 0, 0xA0, 0x0F]);
    assert_eq!(blocks[1].base_address, 0x007FFE9000);
    assert_eq!(blocks[1].size, 0x1000);
    assert_eq!(blocks[1].bytes[0..8], [0x48, 0x61, 0x6C, 0x54, 0, 0, 0, 0]);
    assert_eq!(blocks[2].base_address, 0x9897D0D000);
    assert_eq!(blocks[2].size, 0x3000);
    assert_eq!(blocks[2].bytes[0..8], [0, 0, 0, 0, 0, 0, 0, 0]);
}

[ Dauer der Verarbeitung: 0.30 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge