mirror of
https://github.com/Momoko-Ayase/Senbei.git
synced 2026-11-04 10:31:29 -05:00
fix: scope panic suppression to individual jobs and threads
This commit is contained in:
1 parent
db2729737f
commit
312a70b7c6
5 files changed
+273
-143
No files matched your search
@@ -0,0 +1,68 @@
|
|||||||
|
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||||
|
use std::sync::{Arc, Barrier};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn folder_runs_preserve_the_host_panic_hook() {
|
||||||
|
const CHILD: &str = "SENBEI_PANIC_HOOK_TEST_CHILD";
|
||||||
|
if std::env::var_os(CHILD).is_none() {
|
||||||
|
let output = std::process::Command::new(std::env::current_exe().unwrap())
|
||||||
|
.args([
|
||||||
|
"--exact",
|
||||||
|
"folder_runs_preserve_the_host_panic_hook",
|
||||||
|
"--nocapture",
|
||||||
|
])
|
||||||
|
.env(CHILD, "1")
|
||||||
|
.output()
|
||||||
|
.unwrap();
|
||||||
|
assert!(
|
||||||
|
output.status.success(),
|
||||||
|
"child failed: {}\n{}",
|
||||||
|
String::from_utf8_lossy(&output.stdout),
|
||||||
|
String::from_utf8_lossy(&output.stderr)
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static CALLS: AtomicUsize = AtomicUsize::new(0);
|
||||||
|
std::panic::set_hook(Box::new(|_| {
|
||||||
|
CALLS.fetch_add(1, Ordering::SeqCst);
|
||||||
|
}));
|
||||||
|
let root = tempfile::tempdir().unwrap();
|
||||||
|
// Exercise repeated job lifetimes both before and after engine capture.
|
||||||
|
for _ in 0..2 {
|
||||||
|
senbei_io::job::run_folder_opts(root.path(), None, 2, false, true, false).unwrap();
|
||||||
|
assert!(senbei_engine::catch_unwind_quiet(|| panic!("captured")).is_err());
|
||||||
|
assert!(std::panic::catch_unwind(|| panic!("host")).is_err());
|
||||||
|
}
|
||||||
|
assert_eq!(CALLS.load(Ordering::SeqCst), 2);
|
||||||
|
|
||||||
|
let barrier = Arc::new(Barrier::new(2));
|
||||||
|
let worker_barrier = barrier.clone();
|
||||||
|
let worker = std::thread::spawn(move || {
|
||||||
|
senbei_engine::catch_unwind_quiet(|| {
|
||||||
|
worker_barrier.wait();
|
||||||
|
worker_barrier.wait();
|
||||||
|
panic!("captured in another thread");
|
||||||
|
})
|
||||||
|
.unwrap_err();
|
||||||
|
});
|
||||||
|
barrier.wait();
|
||||||
|
// A quiet capture in another thread must not silence unrelated panics.
|
||||||
|
assert!(std::panic::catch_unwind(|| panic!("unrelated host panic")).is_err());
|
||||||
|
barrier.wait();
|
||||||
|
worker.join().unwrap();
|
||||||
|
assert_eq!(CALLS.load(Ordering::SeqCst), 3);
|
||||||
|
|
||||||
|
std::thread::scope(|scope| {
|
||||||
|
for _ in 0..4 {
|
||||||
|
let path = root.path();
|
||||||
|
scope.spawn(move || {
|
||||||
|
senbei_io::job::run_folder_opts(path, None, 2, false, true, false).unwrap();
|
||||||
|
assert!(
|
||||||
|
senbei_engine::catch_unwind_quiet(|| panic!("after concurrent job")).is_err()
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
assert_eq!(CALLS.load(Ordering::SeqCst), 3);
|
||||||
|
}
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
//! Platform-specific unpacking engines.
|
//! Platform-specific unpacking engines.
|
||||||
|
|
||||||
pub mod android;
|
pub mod android;
|
||||||
|
mod panic_capture;
|
||||||
pub mod windows;
|
pub mod windows;
|
||||||
|
|
||||||
|
pub use panic_capture::catch_unwind_quiet;
|
||||||
|
|
||||||
pub use windows::{
|
pub use windows::{
|
||||||
Detected, IntegrityReport, Kind, UnpackError, check_integrity, detect, unpack_auto,
|
Detected, IntegrityReport, Kind, UnpackError, check_integrity, detect, unpack_auto,
|
||||||
unpack_auto_v, unpack_dll, unpack_dll_v, unpack_exe, unpack_exe_v,
|
unpack_auto_v, unpack_dll, unpack_dll_v, unpack_exe, unpack_exe_v,
|
||||||
|
|||||||
@@ -0,0 +1,182 @@
|
|||||||
|
//! Thread-scoped panic capture shared by the engines and native orchestration.
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub(crate) struct PanicCapture(Arc<Mutex<Option<PanicDetails>>>);
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub(crate) struct PanicDetails {
|
||||||
|
pub message: String,
|
||||||
|
pub file: String,
|
||||||
|
pub line: u32,
|
||||||
|
pub column: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_local! {
|
||||||
|
static ACTIVE_PANIC_CAPTURE: RefCell<Option<PanicCapture>> = const { RefCell::new(None) };
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PanicCaptureGuard(Option<PanicCapture>);
|
||||||
|
|
||||||
|
impl Drop for PanicCaptureGuard {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
ACTIVE_PANIC_CAPTURE.with(|slot| {
|
||||||
|
slot.replace(self.0.take());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PanicCapture {
|
||||||
|
pub(crate) fn new() -> Self {
|
||||||
|
Self(Arc::new(Mutex::new(None)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn record(&self, info: &std::panic::PanicHookInfo<'_>) {
|
||||||
|
let location = info.location();
|
||||||
|
let details = PanicDetails {
|
||||||
|
message: panic_message(info.payload()),
|
||||||
|
file: location
|
||||||
|
.map(|value| value.file().to_owned())
|
||||||
|
.unwrap_or_else(|| "<unknown>".to_owned()),
|
||||||
|
line: location.map_or(0, std::panic::Location::line),
|
||||||
|
column: location.map_or(0, std::panic::Location::column),
|
||||||
|
};
|
||||||
|
let mut captured = self
|
||||||
|
.0
|
||||||
|
.lock()
|
||||||
|
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||||
|
if captured.is_none() {
|
||||||
|
*captured = Some(details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn details(&self, payload: &(dyn std::any::Any + Send)) -> PanicDetails {
|
||||||
|
self.0
|
||||||
|
.lock()
|
||||||
|
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(|| PanicDetails {
|
||||||
|
message: panic_message(payload),
|
||||||
|
file: "<unknown>".to_owned(),
|
||||||
|
line: 0,
|
||||||
|
column: 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn merge_from(&self, other: &Self) {
|
||||||
|
let details = other
|
||||||
|
.0
|
||||||
|
.lock()
|
||||||
|
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
||||||
|
.clone();
|
||||||
|
let Some(details) = details else { return };
|
||||||
|
let mut captured = self
|
||||||
|
.0
|
||||||
|
.lock()
|
||||||
|
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
||||||
|
if captured.is_none() {
|
||||||
|
*captured = Some(details);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn panic_message(payload: &(dyn std::any::Any + Send)) -> String {
|
||||||
|
if let Some(message) = payload.downcast_ref::<&str>() {
|
||||||
|
(*message).to_owned()
|
||||||
|
} else if let Some(message) = payload.downcast_ref::<String>() {
|
||||||
|
message.clone()
|
||||||
|
} else {
|
||||||
|
"non-string panic payload".to_owned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn install_hook() {
|
||||||
|
static INSTALL: std::sync::Once = std::sync::Once::new();
|
||||||
|
INSTALL.call_once(|| {
|
||||||
|
let previous = std::panic::take_hook();
|
||||||
|
std::panic::set_hook(Box::new(move |info| {
|
||||||
|
let capture = ACTIVE_PANIC_CAPTURE
|
||||||
|
.try_with(|slot| slot.try_borrow().ok().and_then(|slot| slot.clone()))
|
||||||
|
.ok()
|
||||||
|
.flatten();
|
||||||
|
if let Some(capture) = capture {
|
||||||
|
capture.record(info);
|
||||||
|
// WebAssembly unwinding is unavailable: retain the browser's
|
||||||
|
// diagnostic hook before the unrecoverable trap.
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
previous(info);
|
||||||
|
} else {
|
||||||
|
previous(info);
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn current_panic_capture() -> Option<PanicCapture> {
|
||||||
|
ACTIVE_PANIC_CAPTURE.with(|slot| slot.borrow().clone())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn with_panic_capture<R>(capture: Option<PanicCapture>, f: impl FnOnce() -> R) -> R {
|
||||||
|
let previous = ACTIVE_PANIC_CAPTURE.with(|slot| slot.replace(capture));
|
||||||
|
let _guard = PanicCaptureGuard(previous);
|
||||||
|
f()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Catch a native per-file panic without printing the process panic hook.
|
||||||
|
///
|
||||||
|
/// Suppression applies only to this thread and scope. The process hook is
|
||||||
|
/// installed once, chains to the host hook outside captures, and is never
|
||||||
|
/// replaced or restored by individual jobs. Nested engine captures and their
|
||||||
|
/// worker-thread diagnostics continue to work independently.
|
||||||
|
///
|
||||||
|
/// Allocation aborts and WebAssembly traps cannot be caught.
|
||||||
|
pub fn catch_unwind_quiet<R>(f: impl FnOnce() -> R) -> std::thread::Result<R> {
|
||||||
|
install_hook();
|
||||||
|
with_panic_capture(Some(PanicCapture::new()), || {
|
||||||
|
std::panic::catch_unwind(std::panic::AssertUnwindSafe(f))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn nested_captures_restore_the_outer_scope() {
|
||||||
|
install_hook();
|
||||||
|
let outer = PanicCapture::new();
|
||||||
|
with_panic_capture(Some(outer.clone()), || {
|
||||||
|
assert!(catch_unwind_quiet(|| panic!("inner panic")).is_err());
|
||||||
|
let payload = std::panic::catch_unwind(|| panic!("outer panic")).unwrap_err();
|
||||||
|
assert_eq!(outer.details(payload.as_ref()).message, "outer panic");
|
||||||
|
});
|
||||||
|
assert!(current_panic_capture().is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn captures_are_thread_local_and_unwind_safe() {
|
||||||
|
install_hook();
|
||||||
|
let workers: Vec<_> = (0..8)
|
||||||
|
.map(|index| {
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
let capture = PanicCapture::new();
|
||||||
|
let payload = with_panic_capture(Some(capture.clone()), || {
|
||||||
|
std::panic::catch_unwind(|| panic!("worker {index}"))
|
||||||
|
})
|
||||||
|
.unwrap_err();
|
||||||
|
assert!(current_panic_capture().is_none());
|
||||||
|
let details = capture.details(payload.as_ref());
|
||||||
|
assert_eq!(details.message, format!("worker {index}"));
|
||||||
|
assert!(details.file.ends_with("panic_capture.rs"));
|
||||||
|
assert!(details.line > 0);
|
||||||
|
assert!(details.column > 0);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
for worker in workers {
|
||||||
|
worker.join().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,8 +8,8 @@ mod layout;
|
|||||||
pub(crate) mod parallel;
|
pub(crate) mod parallel;
|
||||||
|
|
||||||
use senbei_crypto::primitives;
|
use senbei_crypto::primitives;
|
||||||
use std::cell::RefCell;
|
|
||||||
use std::sync::{Arc, Mutex};
|
pub(crate) use crate::panic_capture::{PanicCapture, current_panic_capture, with_panic_capture};
|
||||||
|
|
||||||
pub use crate::thread_cap;
|
pub use crate::thread_cap;
|
||||||
pub use dll::{unpack_dll, unpack_dll_v};
|
pub use dll::{unpack_dll, unpack_dll_v};
|
||||||
@@ -26,130 +26,6 @@ pub use integrity::{
|
|||||||
/// Real protected binaries are far below this.
|
/// Real protected binaries are far below this.
|
||||||
pub(crate) const MAX_IMAGE_SIZE: u64 = senbei_crypto::MAX_IMAGE_SIZE;
|
pub(crate) const MAX_IMAGE_SIZE: u64 = senbei_crypto::MAX_IMAGE_SIZE;
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub(crate) struct PanicCapture(Arc<Mutex<Option<PanicDetails>>>);
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct PanicDetails {
|
|
||||||
message: String,
|
|
||||||
file: String,
|
|
||||||
line: u32,
|
|
||||||
column: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
thread_local! {
|
|
||||||
static ACTIVE_PANIC_CAPTURE: RefCell<Option<PanicCapture>> = const { RefCell::new(None) };
|
|
||||||
}
|
|
||||||
|
|
||||||
struct PanicCaptureGuard(Option<PanicCapture>);
|
|
||||||
|
|
||||||
impl Drop for PanicCaptureGuard {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
ACTIVE_PANIC_CAPTURE.with(|slot| {
|
|
||||||
slot.replace(self.0.take());
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PanicCapture {
|
|
||||||
fn new() -> Self {
|
|
||||||
Self(Arc::new(Mutex::new(None)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn record(&self, info: &std::panic::PanicHookInfo<'_>) {
|
|
||||||
let location = info.location();
|
|
||||||
let details = PanicDetails {
|
|
||||||
message: panic_message(info.payload()),
|
|
||||||
file: location
|
|
||||||
.map(|value| value.file().to_owned())
|
|
||||||
.unwrap_or_else(|| "<unknown>".to_owned()),
|
|
||||||
line: location.map_or(0, std::panic::Location::line),
|
|
||||||
column: location.map_or(0, std::panic::Location::column),
|
|
||||||
};
|
|
||||||
let mut captured = self
|
|
||||||
.0
|
|
||||||
.lock()
|
|
||||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
|
||||||
if captured.is_none() {
|
|
||||||
*captured = Some(details);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn into_error(self, payload: &(dyn std::any::Any + Send)) -> UnpackError {
|
|
||||||
let details = self
|
|
||||||
.0
|
|
||||||
.lock()
|
|
||||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
|
||||||
.clone()
|
|
||||||
.unwrap_or_else(|| PanicDetails {
|
|
||||||
message: panic_message(payload),
|
|
||||||
file: "<unknown>".to_owned(),
|
|
||||||
line: 0,
|
|
||||||
column: 0,
|
|
||||||
});
|
|
||||||
UnpackError::InternalPanic {
|
|
||||||
message: details.message,
|
|
||||||
file: details.file,
|
|
||||||
line: details.line,
|
|
||||||
column: details.column,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn merge_from(&self, other: &Self) {
|
|
||||||
let details = other
|
|
||||||
.0
|
|
||||||
.lock()
|
|
||||||
.unwrap_or_else(std::sync::PoisonError::into_inner)
|
|
||||||
.clone();
|
|
||||||
let Some(details) = details else { return };
|
|
||||||
let mut captured = self
|
|
||||||
.0
|
|
||||||
.lock()
|
|
||||||
.unwrap_or_else(std::sync::PoisonError::into_inner);
|
|
||||||
if captured.is_none() {
|
|
||||||
*captured = Some(details);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn panic_message(payload: &(dyn std::any::Any + Send)) -> String {
|
|
||||||
if let Some(message) = payload.downcast_ref::<&str>() {
|
|
||||||
(*message).to_owned()
|
|
||||||
} else if let Some(message) = payload.downcast_ref::<String>() {
|
|
||||||
message.clone()
|
|
||||||
} else {
|
|
||||||
"non-string panic payload".to_owned()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn install_panic_capture_hook() {
|
|
||||||
static INSTALL: std::sync::Once = std::sync::Once::new();
|
|
||||||
INSTALL.call_once(|| {
|
|
||||||
let previous = std::panic::take_hook();
|
|
||||||
std::panic::set_hook(Box::new(move |info| {
|
|
||||||
let capture = ACTIVE_PANIC_CAPTURE
|
|
||||||
.try_with(|slot| slot.borrow().clone())
|
|
||||||
.ok()
|
|
||||||
.flatten();
|
|
||||||
if let Some(capture) = capture {
|
|
||||||
capture.record(info);
|
|
||||||
} else {
|
|
||||||
previous(info);
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn current_panic_capture() -> Option<PanicCapture> {
|
|
||||||
ACTIVE_PANIC_CAPTURE.with(|slot| slot.borrow().clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn with_panic_capture<R>(capture: Option<PanicCapture>, f: impl FnOnce() -> R) -> R {
|
|
||||||
let previous = ACTIVE_PANIC_CAPTURE.with(|slot| slot.replace(capture));
|
|
||||||
let _guard = PanicCaptureGuard(previous);
|
|
||||||
f()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Run an unpack pipeline, converting any internal panic into a clean
|
/// Run an unpack pipeline, converting any internal panic into a clean
|
||||||
/// [`UnpackError::InternalPanic`] so the public API stays panic-free on any input
|
/// [`UnpackError::InternalPanic`] so the public API stays panic-free on any input
|
||||||
/// (truncated/garbled files chase offsets out of bounds). The panic location and
|
/// (truncated/garbled files chase offsets out of bounds). The panic location and
|
||||||
@@ -161,14 +37,22 @@ pub(crate) fn catch_unpack<F>(f: F) -> Result<Vec<u8>, UnpackError>
|
|||||||
where
|
where
|
||||||
F: FnOnce() -> Result<Vec<u8>, UnpackError>,
|
F: FnOnce() -> Result<Vec<u8>, UnpackError>,
|
||||||
{
|
{
|
||||||
install_panic_capture_hook();
|
crate::panic_capture::install_hook();
|
||||||
let capture = PanicCapture::new();
|
let capture = PanicCapture::new();
|
||||||
let r = with_panic_capture(Some(capture.clone()), || {
|
let r = with_panic_capture(Some(capture.clone()), || {
|
||||||
std::panic::catch_unwind(std::panic::AssertUnwindSafe(f))
|
std::panic::catch_unwind(std::panic::AssertUnwindSafe(f))
|
||||||
});
|
});
|
||||||
match r {
|
match r {
|
||||||
Ok(result) => result,
|
Ok(result) => result,
|
||||||
Err(payload) => Err(capture.into_error(payload.as_ref())),
|
Err(payload) => {
|
||||||
|
let details = capture.details(payload.as_ref());
|
||||||
|
Err(UnpackError::InternalPanic {
|
||||||
|
message: details.message,
|
||||||
|
file: details.file,
|
||||||
|
line: details.line,
|
||||||
|
column: details.column,
|
||||||
|
})
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-15
@@ -165,10 +165,6 @@ pub fn run_folder_opts(
|
|||||||
..Summary::default()
|
..Summary::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Silence the default panic hook's stderr spew during per-file processing.
|
|
||||||
let default_hook = std::panic::take_hook();
|
|
||||||
std::panic::set_hook(Box::new(|_| {})); // suppress "thread panicked" messages
|
|
||||||
|
|
||||||
for input in candidates {
|
for input in candidates {
|
||||||
let rel = rel_in_tree(root, input);
|
let rel = rel_in_tree(root, input);
|
||||||
let dest = out_root.join(out_name(&rel));
|
let dest = out_root.join(out_name(&rel));
|
||||||
@@ -176,9 +172,9 @@ pub fn run_folder_opts(
|
|||||||
// Wrap in catch_unwind so a single bad file never aborts the folder run.
|
// Wrap in catch_unwind so a single bad file never aborts the folder run.
|
||||||
let input_owned = input.clone();
|
let input_owned = input.clone();
|
||||||
let dest_owned = dest.clone();
|
let dest_owned = dest.clone();
|
||||||
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
|
let result = senbei_engine::catch_unwind_quiet(|| {
|
||||||
unpack_one_v(&input_owned, &dest_owned, verbose_steps)
|
unpack_one_v(&input_owned, &dest_owned, verbose_steps)
|
||||||
}));
|
});
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok(Ok((kind, report))) => {
|
Ok(Ok((kind, report))) => {
|
||||||
@@ -246,14 +242,14 @@ pub fn run_folder_opts(
|
|||||||
}
|
}
|
||||||
let input_owned = input.clone();
|
let input_owned = input.clone();
|
||||||
let dest_owned = dest.clone();
|
let dest_owned = dest.clone();
|
||||||
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
|
let result = senbei_engine::catch_unwind_quiet(|| {
|
||||||
crate::android::restore_so_file_with_method_index_module(
|
crate::android::restore_so_file_with_method_index_module(
|
||||||
&input_owned,
|
&input_owned,
|
||||||
&dest_owned,
|
&dest_owned,
|
||||||
verbose_steps,
|
verbose_steps,
|
||||||
&mut android_method_index_module,
|
&mut android_method_index_module,
|
||||||
)
|
)
|
||||||
}));
|
});
|
||||||
match result {
|
match result {
|
||||||
Ok(Ok(embedded)) => {
|
Ok(Ok(embedded)) => {
|
||||||
s.unpacked += 1;
|
s.unpacked += 1;
|
||||||
@@ -325,7 +321,7 @@ pub fn run_folder_opts(
|
|||||||
let rel_owned = rel.clone().into_owned();
|
let rel_owned = rel.clone().into_owned();
|
||||||
let out_root_owned = out_root.clone();
|
let out_root_owned = out_root.clone();
|
||||||
let mut seen_taken = std::mem::take(&mut android_seen);
|
let mut seen_taken = std::mem::take(&mut android_seen);
|
||||||
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
|
let result = senbei_engine::catch_unwind_quiet(|| {
|
||||||
let outcomes = crate::android::restore_package_with_method_index_module(
|
let outcomes = crate::android::restore_package_with_method_index_module(
|
||||||
&package_owned,
|
&package_owned,
|
||||||
&rel_owned,
|
&rel_owned,
|
||||||
@@ -335,7 +331,7 @@ pub fn run_folder_opts(
|
|||||||
&mut android_method_index_module,
|
&mut android_method_index_module,
|
||||||
);
|
);
|
||||||
(outcomes, seen_taken)
|
(outcomes, seen_taken)
|
||||||
}));
|
});
|
||||||
match result {
|
match result {
|
||||||
Ok((Ok(outcomes), seen_back)) => {
|
Ok((Ok(outcomes), seen_back)) => {
|
||||||
android_seen = seen_back;
|
android_seen = seen_back;
|
||||||
@@ -377,14 +373,14 @@ pub fn run_folder_opts(
|
|||||||
let dest = out_root.join(out_name(&rel));
|
let dest = out_root.join(out_name(&rel));
|
||||||
let meta_owned = meta.clone();
|
let meta_owned = meta.clone();
|
||||||
let dest_owned = dest.clone();
|
let dest_owned = dest.clone();
|
||||||
let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
|
let result = senbei_engine::catch_unwind_quiet(|| {
|
||||||
deobfuscate_metadata_to_with_module(
|
deobfuscate_metadata_to_with_module(
|
||||||
&meta_owned,
|
&meta_owned,
|
||||||
&dest_owned,
|
&dest_owned,
|
||||||
verbose_steps,
|
verbose_steps,
|
||||||
android_method_index_module.as_deref(),
|
android_method_index_module.as_deref(),
|
||||||
)
|
)
|
||||||
}));
|
});
|
||||||
match result {
|
match result {
|
||||||
Ok(Ok(report)) if report.remapped > 0 => {
|
Ok(Ok(report)) if report.remapped > 0 => {
|
||||||
s.metadata += 1;
|
s.metadata += 1;
|
||||||
@@ -453,9 +449,6 @@ pub fn run_folder_opts(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore the original panic hook.
|
|
||||||
std::panic::set_hook(default_hook);
|
|
||||||
|
|
||||||
bar.finish_and_clear();
|
bar.finish_and_clear();
|
||||||
s.duration_ms = t0.elapsed().as_millis();
|
s.duration_ms = t0.elapsed().as_millis();
|
||||||
if let Some(log) = &log {
|
if let Some(log) = &log {
|
||||||
|
|||||||
Reference in new issue
Block a user