From 74bbeb9bda024cd4e49b0b4c084b625c0cb29e17 Mon Sep 17 00:00:00 2001 From: NkBe Date: Tue, 10 Feb 2026 17:44:59 +0800 Subject: [PATCH] =?UTF-8?q?patch-loader:=20=E5=84=AA=E5=8C=96=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E5=92=8C=E8=B3=87=E6=BA=90=E8=99=95=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a shared Gson instance and harden config/module/asset loading to avoid NPEs and crashes. Guard legacy module iteration, use apply() for SharedPreferences, throw when config asset is missing, reuse GSON for parsing, and null-check resource streams before copying. Also set provider dex file writable only if created and remove some unused imports. These changes improve resilience when manager/asset data is unavailable and clean up file handling. --- .../lsposed/npatch/loader/LSPApplication.java | 33 +++++++++++-------- .../org/lsposed/npatch/share/Constants.java | 2 +- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/patch-loader/src/main/java/org/lsposed/npatch/loader/LSPApplication.java b/patch-loader/src/main/java/org/lsposed/npatch/loader/LSPApplication.java index c0ec746..ce18141 100644 --- a/patch-loader/src/main/java/org/lsposed/npatch/loader/LSPApplication.java +++ b/patch-loader/src/main/java/org/lsposed/npatch/loader/LSPApplication.java @@ -41,13 +41,11 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.nio.file.attribute.PosixFilePermissions; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.function.BiConsumer; -import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import dalvik.system.DexFile; @@ -66,6 +64,8 @@ public class LSPApplication { private static final int FIRST_APP_ZYGOTE_ISOLATED_UID = 90000; private static final int PER_USER_RANGE = 100000; + private static final Gson GSON = new Gson(); + private static ActivityThread activityThread; private static LoadedApk stubLoadedApk; private static LoadedApk appLoadedApk; @@ -105,16 +105,18 @@ public class LSPApplication { service = new RemoteApplicationService(context); List m = service.getLegacyModulesList(); JSONArray moduleArr = new JSONArray(); - for (Module module : m) { - JSONObject moduleObj = new JSONObject(); - moduleObj.put("path", module.apkPath); - moduleObj.put("packageName", module.packageName); - moduleArr.put(moduleObj); + if (m != null) { + for (Module module : m) { + JSONObject moduleObj = new JSONObject(); + moduleObj.put("path", module.apkPath); + moduleObj.put("packageName", module.packageName); + moduleArr.put(moduleObj); + } } SharedPreferences shared = context.getSharedPreferences("npatch", Context.MODE_PRIVATE); - shared.edit().putString("modules", moduleArr.toString()).commit(); + shared.edit().putString("modules", moduleArr.toString()).apply(); Log.e(TAG, "Success update module scope"); - }catch (Exception e){ + } catch (Exception e) { Log.e(TAG, "Failed to connect to manager, fallback to fixed local service"); service = new NeoLocalApplicationService(context); } @@ -153,8 +155,9 @@ public class LSPApplication { var baseClassLoader = stubLoadedApk.getClassLoader(); try (var is = baseClassLoader.getResourceAsStream(CONFIG_ASSET_PATH)) { + if (is == null) throw new IOException("Config file not found in assets"); BufferedReader streamReader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8)); - config = new Gson().fromJson(streamReader, PatchConfig.class); + config = GSON.fromJson(streamReader, PatchConfig.class); } catch (IOException e) { Log.e(TAG, "Failed to load config file", e); return null; @@ -180,7 +183,7 @@ public class LSPApplication { FileUtils.deleteFolderIfExists(originPath); Files.createDirectories(originPath); try (InputStream is = baseClassLoader.getResourceAsStream(ORIGINAL_APK_ASSET_PATH)) { - Files.copy(is, cacheApkPath); + if (is != null) Files.copy(is, cacheApkPath); } } Path providerPath = null; @@ -189,9 +192,13 @@ public class LSPApplication { try { Files.deleteIfExists(providerPath); try (InputStream is = baseClassLoader.getResourceAsStream(PROVIDER_DEX_ASSET_PATH)) { - Files.copy(is, providerPath); + if (is != null) Files.copy(is, providerPath); + } + if (Files.exists(providerPath)) { + providerPath.toFile().setWritable(false); + } else { + providerPath = null; } - providerPath.toFile().setWritable(false); } catch (Exception e) { Log.e(TAG, "Failed to inject provider:" + Log.getStackTraceString(e)); providerPath = null; diff --git a/share/java/src/main/java/org/lsposed/npatch/share/Constants.java b/share/java/src/main/java/org/lsposed/npatch/share/Constants.java index 487d9cd..55546cd 100644 --- a/share/java/src/main/java/org/lsposed/npatch/share/Constants.java +++ b/share/java/src/main/java/org/lsposed/npatch/share/Constants.java @@ -6,7 +6,7 @@ public class Constants { final static public String LOADER_DEX_ASSET_PATH = "assets/npatch/loader.dex"; final static public String META_LOADER_DEX_ASSET_PATH = "assets/npatch/metaloader.dex"; final static public String PROVIDER_DEX_ASSET_PATH = "assets/npatch/mtprovider.dex"; - final static public String ORIGINAL_APK_ASSET_PATH = "assets/npatch/origin.apk.np"; + final static public String ORIGINAL_APK_ASSET_PATH = "assets/npatch/origin.apk"; final static public String EMBEDDED_MODULES_ASSET_PATH = "assets/npatch/modules/"; final static public String PATCH_FILE_SUFFIX = "-npatched.apk";