Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error occurs when writing output apk - Splitting not support for pre Lollipop Android (Api 22). #2130

Open
huangkr03 opened this issue Nov 23, 2024 · 4 comments

Comments

@huangkr03
Copy link

Describe the bug
This error occurs when calling PackManager.v().writeOutput(); after analyzing the apk file that minSdkVersion < 22.

Input file
com.nokoprint.apk,its metadata are as follows:
packageName: com.nokoprint
label: NokoPrint
icon: res/mipmap-mdpi-v4/ic_launcher.png
versionName: 5.2.0
versionCode: 230
minSdkVersion: 19
targetSdkVersion: 32
maxSdkVersion: null

To reproduce
It seems that all of the input apks that minSdkVersion < 22 will raise this error when calling PackManager.v().writeOutput();
I also tried Options.v().set_android_api_version(compileSdkVersion); and Options.v().set_android_api_version(minSdkVersion);. The error keeps occuring.

Expected behavior
Error will occur when calling PackManager.v().writeOutput();

Stacktrace

Exception in thread "Thread-64" java.lang.RuntimeException: Dex file overflow. Splitting not support for pre Lollipop Android (Api 22).
at soot.toDex.MultiDexBuilder.hasOverflowed(MultiDexBuilder.java:96)
at soot.toDex.MultiDexBuilder.internClass(MultiDexBuilder.java:58)
at soot.toDex.DexPrinter.addAsClassDefItem(DexPrinter.java:663)
at soot.toDex.DexPrinter.add(DexPrinter.java:1686)
at soot.PackManager.writeClass(PackManager.java:1072)
at soot.PackManager.lambda$writeOutput$1(PackManager.java:705)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:829)

Additional context
I tried to use apktool to reset the minSdkVersion of the app, and the error disappeared. But this process is too troublesome.
So I wonder if soot could help modify the minSdkVersion when calling PackManager.v().writeOutput();.

@jpstotz
Copy link
Contributor

jpstotz commented Nov 25, 2024

Have you read the comment in source code where that exception is thrown?

protected boolean hasOverflowed() {
if (!curPool.hasOverflowed()) {
return false;
}
// We only support splitting for api versions since Lollipop (22).
// Since Api 22, Art runtime is used which needs to extract all dex
// files anyway. Thus,
// we can pack classes arbitrarily and do not need to care about which
// classes need to go together in
// the same dex file.
// For Dalvik (pre 22), it is important that at least the main dex file
// (classes.dex) contains all needed
// dependencies of the Main activity, which means that one would have to
// determine necessary dependencies and
// pack those explicitly in the first dex file.
// (https://developer.android.com/studio/build/multidex.html,
// http://www.fasteque.com/deep-dive-into-android-multidex/)
if (!opcodes.isArt()) {
throw new RuntimeException("Dex file overflow. Splitting not support for pre Lollipop Android (Api 22).");
}
return true;
}

@huangkr03
Copy link
Author

Have you read the comment in source code where that exception is thrown?

protected boolean hasOverflowed() {
if (!curPool.hasOverflowed()) {
return false;
}
// We only support splitting for api versions since Lollipop (22).
// Since Api 22, Art runtime is used which needs to extract all dex
// files anyway. Thus,
// we can pack classes arbitrarily and do not need to care about which
// classes need to go together in
// the same dex file.
// For Dalvik (pre 22), it is important that at least the main dex file
// (classes.dex) contains all needed
// dependencies of the Main activity, which means that one would have to
// determine necessary dependencies and
// pack those explicitly in the first dex file.
// (https://developer.android.com/studio/build/multidex.html,
// http://www.fasteque.com/deep-dive-into-android-multidex/)
if (!opcodes.isArt()) {
throw new RuntimeException("Dex file overflow. Splitting not support for pre Lollipop Android (Api 22).");
}
return true;
}

Thank you for your response!
I understand the cause of this exception now. But in this case, how can I deal with this problem?

@jpstotz
Copy link
Contributor

jpstotz commented Nov 25, 2024

I assume Scene.getAndroidAPIVersion() returns a value smaller than 22?

You could try to override it using Options.v().android_api_version(22) before loading the APK.

@huangkr03
Copy link
Author

I assume Scene.getAndroidAPIVersion() returns a value smaller than 22?

You could try to override it using Options.v().android_api_version(22) before loading the APK.

I tried to set API 22 as Options.v().set_android_api_version(22); before loading the APK, but the same error occurs as well.
I also tried API 19 and 32, the results are the same.

The source code for the options settings is presented below

Options.v().set_no_bodies_for_excluded(true);
Options.v().set_allow_phantom_refs(true);
Options.v().set_whole_program(true);
Options.v().set_process_multiple_dex(true);
Options.v().set_keep_line_number(false);
Options.v().set_keep_offset(false);
Options.v().set_ignore_resolution_errors(true);

Options.v().set_output_format(Options.output_format_dex);
Options.v().set_src_prec(Options.src_prec_apk_class_jimple);
Options.v().set_process_dir(List.of(apkPath));
Options.v().set_throw_analysis(Options.throw_analysis_dalvik);

Options.v().set_exclude(Arrays.asList(Constant.EXCLUDE_LIST));
Options.v().set_no_bodies_for_excluded(true);

Options.v().set_force_overwrite(true);
Options.v().set_output_dir(Config.INSTRUMENTED_APKS_PATH);

Options.v().set_android_api_version(22);

Scene.v().loadNecessaryClasses();

PackManager.v().runPacks();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants