fix: composer crash
This commit is contained in:
@@ -4,7 +4,7 @@ declare var _getImportsFunctionName: string;
|
|||||||
declare var _runtimeName: boolean;
|
declare var _runtimeName: boolean;
|
||||||
export const runtimeName = _runtimeName;
|
export const runtimeName = _runtimeName;
|
||||||
|
|
||||||
const remoteImports = require(_runtimeName + '_core/src/DeviceBridge')[_getImportsFunctionName]();
|
const remoteImports = require(_runtimeName + '_core/DeviceBridge')[_getImportsFunctionName]();
|
||||||
|
|
||||||
function callRemoteFunction(method: string, ...args: any[]): any | null {
|
function callRemoteFunction(method: string, ...args: any[]): any | null {
|
||||||
return remoteImports[method](...args);
|
return remoteImports[method](...args);
|
||||||
|
|||||||
@@ -12,7 +12,13 @@ try {
|
|||||||
|
|
||||||
if (config.composerLogs) {
|
if (config.composerLogs) {
|
||||||
["log", "error", "warn", "info", "debug"].forEach(method => {
|
["log", "error", "warn", "info", "debug"].forEach(method => {
|
||||||
console[method] = (...args: any) => log(method, Array.from(args).join(" "));
|
console[method] = (...args: any) => log(method, Array.from(args).map(arg => {
|
||||||
|
try {
|
||||||
|
return typeof arg === 'object' && arg !== null ? JSON.stringify(arg) : String(arg);
|
||||||
|
} catch (e) {
|
||||||
|
return '[unserializable]';
|
||||||
|
}
|
||||||
|
}).join(' '));
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -67,12 +67,23 @@ class ComposerHooks: Feature("ComposerHooks") {
|
|||||||
result = (context.native.composerEval("""
|
result = (context.native.composerEval("""
|
||||||
(() => {
|
(() => {
|
||||||
try {
|
try {
|
||||||
$codeContent
|
const retVal = (() => { $codeContent })();
|
||||||
|
if (typeof retVal === 'undefined') {
|
||||||
|
return 'undefined';
|
||||||
|
}
|
||||||
|
if (retVal === null) {
|
||||||
|
return 'null';
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return JSON.stringify(retVal, null, 2);
|
||||||
|
} catch {
|
||||||
|
return retVal.toString();
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return e.toString()
|
return e.toString()
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
""".trimIndent()) ?: "(no result)").also {
|
""".trimIndent()) ?: "(no result)").toString().also {
|
||||||
context.log.verbose("result: $it", "ComposerConsole")
|
context.log.verbose("result: $it", "ComposerConsole")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,7 +185,7 @@ class ComposerHooks: Feature("ComposerHooks") {
|
|||||||
const i = setInterval(() => {
|
const i = setInterval(() => {
|
||||||
try {
|
try {
|
||||||
const _runtimeName = "${if (SnapEnhance.classCache.nativeBridge.name == "com.snapchat.client.valdi.NativeBridge") "valdi" else "composer"}";
|
const _runtimeName = "${if (SnapEnhance.classCache.nativeBridge.name == "com.snapchat.client.valdi.NativeBridge") "valdi" else "composer"}";
|
||||||
require(_runtimeName + '_core/src/DeviceBridge').getDisplayWidth();
|
require(_runtimeName + '_core/DeviceBridge').getDisplayWidth();
|
||||||
clearInterval(i);
|
clearInterval(i);
|
||||||
(() => { const _getImportsFunctionName = "$getImportsFunctionName"; $loaderScript })();
|
(() => { const _getImportsFunctionName = "$getImportsFunctionName"; $loaderScript })();
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
|
|||||||
@@ -108,25 +108,26 @@ android {
|
|||||||
sourceSets["main"].jniLibs.srcDir("build/rustJniLibs/android")
|
sourceSets["main"].jniLibs.srcDir("build/rustJniLibs/android")
|
||||||
}
|
}
|
||||||
|
|
||||||
val rustupTargetTasks = cargoTargets.mapIndexed { i, target ->
|
// Register rustup tasks
|
||||||
|
val rustupTasks = cargoTargets.map { target ->
|
||||||
tasks.register<Exec>("rustup${target.taskSuffix}") {
|
tasks.register<Exec>("rustup${target.taskSuffix}") {
|
||||||
group = "build"
|
|
||||||
workingDir = file("rust")
|
workingDir = file("rust")
|
||||||
// Idempotent add (only if missing)
|
commandLine("rustup", "target", "add", target.triple)
|
||||||
commandLine(
|
}
|
||||||
"sh", "-c",
|
}
|
||||||
"rustup target list --installed | grep -q ${target.triple} || rustup target add ${target.triple}"
|
|
||||||
)
|
|
||||||
|
|
||||||
if (i > 0) {
|
// Ensure rustup task ordering
|
||||||
val previousTaskName = "rustup${cargoTargets[i - 1].taskSuffix}"
|
rustupTasks.forEachIndexed { index, task ->
|
||||||
mustRunAfter(tasks.named(previousTaskName))
|
if (index > 0) {
|
||||||
|
task.configure {
|
||||||
|
mustRunAfter(rustupTasks[index - 1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val syncTasks = cargoTargets.map { target ->
|
// Register sync & cargo build tasks
|
||||||
val rustupTask = tasks.named("rustup${target.taskSuffix}")
|
val syncTasks = cargoTargets.mapIndexed { index, target ->
|
||||||
|
val rustupTask = rustupTasks[index]
|
||||||
val cargoTask = tasks.register<Exec>("cargoBuild${target.taskSuffix}") {
|
val cargoTask = tasks.register<Exec>("cargoBuild${target.taskSuffix}") {
|
||||||
group = "build"
|
group = "build"
|
||||||
dependsOn(rustupTask)
|
dependsOn(rustupTask)
|
||||||
|
|||||||
@@ -185,12 +185,23 @@ pub unsafe fn composer_eval(env: JNIEnv, _: *mut c_void, script: JString) -> job
|
|||||||
{
|
{
|
||||||
let mut env = env;
|
let mut env = env;
|
||||||
|
|
||||||
let script_str = get_jni_string(&mut env, script).expect("Failed to get script");
|
let script_str = match get_jni_string(&mut env, script) {
|
||||||
|
Ok(s) => s,
|
||||||
|
Err(_) => return std::ptr::null_mut(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if JS_EVAL_ORIGINAL2.is_none() || GLOBAL_INSTANCE.is_none() || GLOBAL_CTX.is_none() {
|
||||||
|
if let Ok(s) = env.new_string("Composer hook not initialized") {
|
||||||
|
return s.into_raw();
|
||||||
|
}
|
||||||
|
return std::ptr::null_mut();
|
||||||
|
}
|
||||||
|
|
||||||
let script_length = script_str.len();
|
let script_length = script_str.len();
|
||||||
|
|
||||||
let js_value = JS_EVAL_ORIGINAL2.expect("No js eval found")(
|
let js_value = JS_EVAL_ORIGINAL2.unwrap()(
|
||||||
GLOBAL_INSTANCE.expect("No global instance found"),
|
GLOBAL_INSTANCE.unwrap(),
|
||||||
GLOBAL_CTX.expect("No global context found"),
|
GLOBAL_CTX.unwrap(),
|
||||||
std::ptr::null_mut(),
|
std::ptr::null_mut(),
|
||||||
(script_str + "\0").as_ptr() as *mut u8,
|
(script_str + "\0").as_ptr() as *mut u8,
|
||||||
script_length,
|
script_length,
|
||||||
@@ -200,29 +211,34 @@ pub unsafe fn composer_eval(env: JNIEnv, _: *mut c_void, script: JString) -> job
|
|||||||
|
|
||||||
let result: String = if js_value.tag == JS_TAG_STRING {
|
let result: String = if js_value.tag == JS_TAG_STRING {
|
||||||
let string = js_value.u.ptr as *mut JsString;
|
let string = js_value.u.ptr as *mut JsString;
|
||||||
CStr::from_ptr((*string).str8.as_ptr() as *const u8).to_str().unwrap().into()
|
match CStr::from_ptr((*string).str8.as_ptr() as *const u8).to_str() {
|
||||||
|
Ok(s) => s.to_string(),
|
||||||
|
Err(_) => "[invalid string]".to_string(),
|
||||||
|
}
|
||||||
} else if js_value.tag == JS_TAG_INT {
|
} else if js_value.tag == JS_TAG_INT {
|
||||||
js_value.u.int32.to_string()
|
js_value.u.int32.to_string()
|
||||||
} else if js_value.tag == JS_TAG_BOOL {
|
} else if js_value.tag == JS_TAG_BOOL {
|
||||||
if js_value.u.int32 == 1 { "true" } else { "false" }.into()
|
if js_value.u.int32 == 1 { "true" } else { "false" }.to_string()
|
||||||
} else if js_value.tag == JS_TAG_NULL {
|
} else if js_value.tag == JS_TAG_NULL {
|
||||||
"null".into()
|
"null".to_string()
|
||||||
} else if js_value.tag == JS_TAG_UNDEFINED {
|
} else if js_value.tag == JS_TAG_UNDEFINED {
|
||||||
"undefined".into()
|
"undefined".to_string()
|
||||||
} else if js_value.tag == JS_TAG_OBJECT {
|
} else if js_value.tag == JS_TAG_OBJECT {
|
||||||
"[object]".into()
|
"[object]".to_string()
|
||||||
} else if js_value.tag == JS_TAG_FLOAT64 {
|
} else if js_value.tag == JS_TAG_FLOAT64 {
|
||||||
js_value.u.float64.to_string()
|
js_value.u.float64.to_string()
|
||||||
} else if js_value.tag == JS_TAG_EXCEPTION {
|
} else if js_value.tag == JS_TAG_EXCEPTION {
|
||||||
"Failed to evaluate script".into()
|
"Failed to evaluate script".to_string()
|
||||||
} else {
|
} else {
|
||||||
"[unknown tag ".to_owned() + &js_value.tag.to_string() + "]".into()
|
format!("[unknown tag {}]", js_value.tag)
|
||||||
};
|
};
|
||||||
|
|
||||||
return env.new_string(result).unwrap().into_raw()
|
if let Ok(s) = env.new_string(result) {
|
||||||
|
return s.into_raw();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return env.new_string("Architecture not supported").unwrap().into_raw();
|
std::ptr::null_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
@@ -237,11 +253,20 @@ pub fn init() {
|
|||||||
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
{
|
{
|
||||||
if let Some(signature) = sig::find_signature(
|
let signature = sig::find_signature(
|
||||||
&common::CLIENT_MODULE,
|
&common::CLIENT_MODULE,
|
||||||
"00 E4 00 6F 29 00 80 52 76 00 04 8B", -0x28,
|
"00 E4 00 6F 29 00 80 52 76 00 04 8B", -0x28,
|
||||||
"A1 B0 07 92 81 46", -0x7
|
"A1 B0 07 92 81 46", -0x7
|
||||||
) {
|
).or_else(|| {
|
||||||
|
warn!("primary js_eval signature failed, trying fallback");
|
||||||
|
sig::find_signature(
|
||||||
|
&common::CLIENT_MODULE,
|
||||||
|
"00 E4 00 6F ?? ?? ?? ?? ?? ?? ?? ??", -0x28,
|
||||||
|
"?? ?? ?? ?? ?? ??", -0x7
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(signature) = signature {
|
||||||
dobby_hook!(signature as *mut c_void, js_eval);
|
dobby_hook!(signature as *mut c_void, js_eval);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|||||||
Reference in New Issue
Block a user