From 66c1b468655d363087a3a58d7d65a1e267bd53b3 Mon Sep 17 00:00:00 2001 From: Marc Miltenberger Date: Tue, 2 May 2017 08:21:09 +0200 Subject: [PATCH] Closing Framework and APK after use This commit should fix https://github.com/iBotPeaches/Apktool/issues/1160 --- .../src/main/java/brut/apktool/Main.java | 5 + .../src/main/java/brut/androlib/Androlib.java | 4 + .../main/java/brut/androlib/ApkDecoder.java | 161 ++++++++++-------- .../brut/androlib/res/AndrolibResources.java | 23 ++- .../brut/directory/AbstractDirectory.java | 6 + .../main/java/brut/directory/Directory.java | 3 + .../src/main/java/brut/directory/ExtFile.java | 5 + .../java/brut/directory/ZipRODirectory.java | 4 + 8 files changed, 136 insertions(+), 75 deletions(-) diff --git a/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java b/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java index 74470801..6e292713 100644 --- a/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java +++ b/brut.apktool/apktool-cli/src/main/java/brut/apktool/Main.java @@ -187,6 +187,11 @@ public class Main { } catch (DirectoryException ex) { System.err.println("Could not modify internal dex files. Please ensure you have permission."); System.exit(1); + } finally { + try { + decoder.close(); + } catch (IOException e) { + } } } diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java index 8a1aaf55..d51cb8d4 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/Androlib.java @@ -741,6 +741,10 @@ public class Androlib { return files; } + public void close() throws IOException { + mAndRes.close(); + } + private final static Logger LOGGER = Logger.getLogger(Androlib.class.getName()); private final static String SMALI_DIRNAME = "smali"; diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java index aa2ca555..72a10488 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/ApkDecoder.java @@ -60,6 +60,14 @@ public class ApkDecoder { } public void setApkFile(File apkFile) { + if (mApkFile != null) + { + try { + mApkFile.close(); + } catch (IOException e) { + } + } + mApkFile = new ExtFile(apkFile); mResTable = null; } @@ -73,93 +81,100 @@ public class ApkDecoder { } public void decode() throws AndrolibException, IOException, DirectoryException { - File outDir = getOutDir(); - AndrolibResources.sKeepBroken = mKeepBrokenResources; - - if (!mForceDelete && outDir.exists()) { - throw new OutDirExistsException(); - } - - if (!mApkFile.isFile() || !mApkFile.canRead()) { - throw new InFileNotFoundException(); - } - try { - OS.rmdir(outDir); - } catch (BrutException ex) { - throw new AndrolibException(ex); - } - outDir.mkdirs(); + File outDir = getOutDir(); + AndrolibResources.sKeepBroken = mKeepBrokenResources; - LOGGER.info("Using Apktool " + Androlib.getVersion() + " on " + mApkFile.getName()); - - if (hasResources()) { - switch (mDecodeResources) { - case DECODE_RESOURCES_NONE: - mAndrolib.decodeResourcesRaw(mApkFile, outDir); - break; - case DECODE_RESOURCES_FULL: - setTargetSdkVersion(); - setAnalysisMode(mAnalysisMode, true); - - if (hasManifest()) { - mAndrolib.decodeManifestWithResources(mApkFile, outDir, getResTable()); - } - mAndrolib.decodeResourcesFull(mApkFile, outDir, getResTable()); - break; + if (!mForceDelete && outDir.exists()) { + throw new OutDirExistsException(); } - } else { - // if there's no resources.asrc, decode the manifest without looking - // up attribute references - if (hasManifest()) { + + if (!mApkFile.isFile() || !mApkFile.canRead()) { + throw new InFileNotFoundException(); + } + + try { + OS.rmdir(outDir); + } catch (BrutException ex) { + throw new AndrolibException(ex); + } + outDir.mkdirs(); + + LOGGER.info("Using Apktool " + Androlib.getVersion() + " on " + mApkFile.getName()); + + if (hasResources()) { switch (mDecodeResources) { case DECODE_RESOURCES_NONE: - mAndrolib.decodeManifestRaw(mApkFile, outDir); + mAndrolib.decodeResourcesRaw(mApkFile, outDir); break; case DECODE_RESOURCES_FULL: - mAndrolib.decodeManifestFull(mApkFile, outDir, - getResTable()); + setTargetSdkVersion(); + setAnalysisMode(mAnalysisMode, true); + + if (hasManifest()) { + mAndrolib.decodeManifestWithResources(mApkFile, outDir, getResTable()); + } + mAndrolib.decodeResourcesFull(mApkFile, outDir, getResTable()); + break; + } + } else { + // if there's no resources.asrc, decode the manifest without looking + // up attribute references + if (hasManifest()) { + switch (mDecodeResources) { + case DECODE_RESOURCES_NONE: + mAndrolib.decodeManifestRaw(mApkFile, outDir); + break; + case DECODE_RESOURCES_FULL: + mAndrolib.decodeManifestFull(mApkFile, outDir, + getResTable()); + break; + } + } + } + + if (hasSources()) { + switch (mDecodeSources) { + case DECODE_SOURCES_NONE: + mAndrolib.decodeSourcesRaw(mApkFile, outDir, "classes.dex"); + break; + case DECODE_SOURCES_SMALI: + mAndrolib.decodeSourcesSmali(mApkFile, outDir, "classes.dex", mBakDeb, mApi); break; } } - } - if (hasSources()) { - switch (mDecodeSources) { - case DECODE_SOURCES_NONE: - mAndrolib.decodeSourcesRaw(mApkFile, outDir, "classes.dex"); - break; - case DECODE_SOURCES_SMALI: - mAndrolib.decodeSourcesSmali(mApkFile, outDir, "classes.dex", mBakDeb, mApi); - break; - } - } - - if (hasMultipleSources()) { - // foreach unknown dex file in root, lets disassemble it - Set files = mApkFile.getDirectory().getFiles(true); - for (String file : files) { - if (file.endsWith(".dex")) { - if (! file.equalsIgnoreCase("classes.dex")) { - switch(mDecodeSources) { - case DECODE_SOURCES_NONE: - mAndrolib.decodeSourcesRaw(mApkFile, outDir, file); - break; - case DECODE_SOURCES_SMALI: - mAndrolib.decodeSourcesSmali(mApkFile, outDir, file, mBakDeb, mApi); - break; + if (hasMultipleSources()) { + // foreach unknown dex file in root, lets disassemble it + Set files = mApkFile.getDirectory().getFiles(true); + for (String file : files) { + if (file.endsWith(".dex")) { + if (! file.equalsIgnoreCase("classes.dex")) { + switch(mDecodeSources) { + case DECODE_SOURCES_NONE: + mAndrolib.decodeSourcesRaw(mApkFile, outDir, file); + break; + case DECODE_SOURCES_SMALI: + mAndrolib.decodeSourcesSmali(mApkFile, outDir, file, mBakDeb, mApi); + break; + } } } } } - } - mAndrolib.decodeRawFiles(mApkFile, outDir); - mAndrolib.decodeUnknownFiles(mApkFile, outDir, mResTable); - mUncompressedFiles = new ArrayList(); - mAndrolib.recordUncompressedFiles(mApkFile, mUncompressedFiles); - mAndrolib.writeOriginalFiles(mApkFile, outDir); - writeMetaFile(); + mAndrolib.decodeRawFiles(mApkFile, outDir); + mAndrolib.decodeUnknownFiles(mApkFile, outDir, mResTable); + mUncompressedFiles = new ArrayList(); + mAndrolib.recordUncompressedFiles(mApkFile, mUncompressedFiles); + mAndrolib.writeOriginalFiles(mApkFile, outDir); + writeMetaFile(); + } finally { + try { + mApkFile.close(); + } catch (IOException e) { + } + } } public void setDecodeSources(short mode) throws AndrolibException { @@ -273,6 +288,10 @@ public class ApkDecoder { } } + public void close() throws IOException { + mAndrolib.close(); + } + public final static short DECODE_SOURCES_NONE = 0x0000; public final static short DECODE_SOURCES_SMALI = 0x0001; diff --git a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java index ae884321..3b308422 100644 --- a/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java +++ b/brut.apktool/apktool-lib/src/main/java/brut/androlib/res/AndrolibResources.java @@ -121,7 +121,8 @@ final public class AndrolibResources { File apk = getFrameworkApk(id, frameTag); LOGGER.info("Loading resource table from file: " + apk); - ResPackage[] pkgs = getResPackagesFromApk(new ExtFile(apk), resTable, true); + mFramework = new ExtFile(apk); + ResPackage[] pkgs = getResPackagesFromApk(mFramework, resTable, true); ResPackage pkg; if (pkgs.length > 1) { @@ -555,15 +556,23 @@ final public class AndrolibResources { private ResPackage[] getResPackagesFromApk(ExtFile apkFile,ResTable resTable, boolean keepBroken) throws AndrolibException { try { - BufferedInputStream bfi = new BufferedInputStream(apkFile.getDirectory().getFileInput("resources.arsc")); - return ARSCDecoder.decode(bfi, false, keepBroken, resTable).getPackages(); + Directory dir = apkFile.getDirectory(); + BufferedInputStream bfi = new BufferedInputStream(dir.getFileInput("resources.arsc")); + try { + return ARSCDecoder.decode(bfi, false, keepBroken, resTable).getPackages(); + } finally { + try { + bfi.close(); + } catch (IOException e) { + } + } } catch (DirectoryException ex) { throw new AndrolibException("Could not load resources.arsc from file: " + apkFile, ex); } } public File getFrameworkApk(int id, String frameTag) - throws AndrolibException { + throws AndrolibException { File dir = getFrameworkDir(); File apk; @@ -810,6 +819,10 @@ final public class AndrolibResources { } } + public void close() throws IOException { + mFramework.close(); + } + public ApkOptions apkOptions; // TODO: dirty static hack. I have to refactor decoding mechanisms. @@ -819,6 +832,8 @@ final public class AndrolibResources { private File mFrameworkDirectory = null; + private ExtFile mFramework = null; + private String mMinSdkVersion = null; private String mMaxSdkVersion = null; private String mTargetSdkVersion = null; diff --git a/brut.j.dir/src/main/java/brut/directory/AbstractDirectory.java b/brut.j.dir/src/main/java/brut/directory/AbstractDirectory.java index c2befcbe..ea906c7a 100644 --- a/brut.j.dir/src/main/java/brut/directory/AbstractDirectory.java +++ b/brut.j.dir/src/main/java/brut/directory/AbstractDirectory.java @@ -17,6 +17,7 @@ package brut.directory; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.LinkedHashMap; @@ -235,6 +236,11 @@ public abstract class AbstractDirectory implements Directory { return dirs; } + + public void close() throws IOException { + + } + private SubPath getSubPath(String path) throws PathNotExist { ParsedPath parsed = parsePath(path); if (parsed.dir == null) { diff --git a/brut.j.dir/src/main/java/brut/directory/Directory.java b/brut.j.dir/src/main/java/brut/directory/Directory.java index 0199135d..e7a972be 100644 --- a/brut.j.dir/src/main/java/brut/directory/Directory.java +++ b/brut.j.dir/src/main/java/brut/directory/Directory.java @@ -50,5 +50,8 @@ public interface Directory { public int getCompressionLevel(String fileName) throws DirectoryException; + + public void close() throws IOException; + public final char separator = '/'; } diff --git a/brut.j.dir/src/main/java/brut/directory/ExtFile.java b/brut.j.dir/src/main/java/brut/directory/ExtFile.java index 583c3fa1..008e1b45 100644 --- a/brut.j.dir/src/main/java/brut/directory/ExtFile.java +++ b/brut.j.dir/src/main/java/brut/directory/ExtFile.java @@ -17,6 +17,7 @@ package brut.directory; import java.io.File; +import java.io.IOException; import java.net.URI; /** @@ -54,5 +55,9 @@ public class ExtFile extends File { return mDirectory; } + public void close() throws IOException { + mDirectory.close(); + } + private Directory mDirectory; } diff --git a/brut.j.dir/src/main/java/brut/directory/ZipRODirectory.java b/brut.j.dir/src/main/java/brut/directory/ZipRODirectory.java index bb76298a..a400ce34 100644 --- a/brut.j.dir/src/main/java/brut/directory/ZipRODirectory.java +++ b/brut.j.dir/src/main/java/brut/directory/ZipRODirectory.java @@ -151,4 +151,8 @@ public class ZipRODirectory extends AbstractDirectory { return mZipFile; } + + public void close() throws IOException { + mZipFile.close(); + } }