use super::*;
#[test]
fn high_level_lifts_try_finally_blocks() {
let script = [0x3B, 0x00, 0x03, 0x11, 0x3D, 0x02, 0x12, 0x3F, 0x40];
let nef_bytes = build_nef(&script);
let decompilation = Decompiler::new()
.decompile_bytes(&nef_bytes)
.expect("decompile succeeds");
let high_level = decompilation
.high_level
.as_deref()
.expect("high-level output");
assert!(
high_level.contains("try {"),
"missing try block: {high_level}"
);
assert!(
high_level.contains("finally {"),
"missing finally block: {high_level}"
);
assert!(
!high_level.contains("end-try ->"),
"structured try should suppress ENDTRY note: {high_level}"
);
assert!(
!high_level.contains("endfinally"),
"structured try should suppress ENDFINALLY note: {high_level}"
);
}
#[test]
fn high_level_lifts_try_catch_blocks() {
let script = [0x3B, 0x03, 0x00, 0x11, 0x3D, 0x03, 0x12, 0x3D, 0x00, 0x40];
let nef_bytes = build_nef(&script);
let decompilation = Decompiler::new()
.decompile_bytes(&nef_bytes)
.expect("decompile succeeds");
let high_level = decompilation
.high_level
.as_deref()
.expect("high-level output");
assert!(
high_level.contains("try {"),
"missing try header: {high_level}"
);
assert!(
high_level.contains("catch {"),
"missing catch header: {high_level}"
);
assert!(
!high_level.contains("end-try ->"),
"structured try should suppress ENDTRY notes: {high_level}"
);
}
#[test]
fn high_level_lifts_try_catch_finally_blocks() {
let script = [
0x3B, 0x03, 0x06, 0x11, 0x3D, 0x05, 0x12, 0x3D, 0x02, 0x13, 0x3F, 0x40,
];
let nef_bytes = build_nef(&script);
let decompilation = Decompiler::new()
.decompile_bytes(&nef_bytes)
.expect("decompile succeeds");
let high_level = decompilation
.high_level
.as_deref()
.expect("high-level output");
assert!(
high_level.contains("try {"),
"missing try header: {high_level}"
);
assert!(
high_level.contains("catch {"),
"missing catch header: {high_level}"
);
assert!(
high_level.contains("finally {"),
"missing finally header: {high_level}"
);
assert!(
!high_level.contains("endfinally"),
"structured try should suppress ENDFINALLY note: {high_level}"
);
}
#[test]
fn high_level_lifts_try_finally_with_throw_inside() {
let script = [
0x3B, 0x00, 0x04, 0x11, 0x3A, 0x3D, 0x02, 0x12, 0x3F, 0x40, ];
let nef_bytes = build_nef(&script);
let decompilation = Decompiler::new()
.decompile_bytes(&nef_bytes)
.expect("decompile succeeds");
let high_level = decompilation
.high_level
.as_deref()
.expect("high-level output");
assert!(
high_level.contains("try {"),
"missing try block: {high_level}"
);
assert!(
high_level.contains("throw("),
"THROW inside try should be lifted: {high_level}"
);
assert!(
high_level.contains("finally {"),
"missing finally block: {high_level}"
);
}
#[test]
fn high_level_lifts_try_catch_with_abort_in_catch() {
let script = [
0x3B, 0x03, 0x00, 0x11, 0x3D, 0x03, 0x38, 0x3D, 0x00, 0x40, ];
let nef_bytes = build_nef(&script);
let decompilation = Decompiler::new()
.decompile_bytes(&nef_bytes)
.expect("decompile succeeds");
let high_level = decompilation
.high_level
.as_deref()
.expect("high-level output");
assert!(
high_level.contains("try {"),
"missing try header: {high_level}"
);
assert!(
high_level.contains("catch {"),
"missing catch header: {high_level}"
);
assert!(
high_level.contains("abort()"),
"ABORT inside catch should be lifted: {high_level}"
);
}
#[test]
fn high_level_models_catch_entry_stack_with_exception_value() {
let script = [
0x3B, 0x06, 0x00, 0x11, 0x3D, 0x06, 0x70, 0x68, 0x3D, 0x00, 0x40, ];
let nef_bytes = build_nef(&script);
let decompilation = Decompiler::new()
.decompile_bytes(&nef_bytes)
.expect("decompile succeeds");
let high_level = decompilation
.high_level
.as_deref()
.expect("high-level output");
assert!(
high_level.contains("catch {"),
"missing catch header: {high_level}"
);
assert!(
high_level.contains("let loc0 = exception;"),
"catch entry should model exception object stack item for STLOC0: {high_level}"
);
assert!(
!high_level.contains("insufficient values on stack"),
"catch entry STLOC0 should not underflow the stack: {high_level}"
);
}