diff --git a/tests/java/com/yqsh/protector/packer/Pvm2RuntimeImages.java b/tests/java/com/yqsh/protector/packer/Pvm2RuntimeImages.java index 681f7f8..62f3cb7 100644 --- a/tests/java/com/yqsh/protector/packer/Pvm2RuntimeImages.java +++ b/tests/java/com/yqsh/protector/packer/Pvm2RuntimeImages.java @@ -137,5 +137,14 @@ public static void main(String[] args) throws Exception { Files.write(Path.of(args[0], "image" + index + ".gcm"), com.yqsh.protector.packer.util.CryptoUtils.aesGcmEncrypt(new byte[16], result.image)); } + // const-wide/32 的负立即数必须符号扩展到 64 位;回归 Integer.MIN_VALUE 边界。 + Code wide = new Code(1, 0, 0, 0, new short[]{0x0017, 0x0000, (short) 0x8000, 0x0010}, + new Code.Try[0], new Code.CatchHandler[0]); + var wideResult = Pvm2Compiler.tryCompile(null, wide, "J", true, + Pvm2Morph.fromIsa(0, new SecureRandom()), true); + if (!wideResult.isOk()) throw new AssertionError("const-wide/32: " + wideResult.failReason); + Files.write(Path.of(args[0], "image90.bin"), wideResult.image); + Files.write(Path.of(args[0], "image90.gcm"), + com.yqsh.protector.packer.util.CryptoUtils.aesGcmEncrypt(new byte[16], wideResult.image)); } } diff --git a/tests/native/pvm2_runtime_check.cpp b/tests/native/pvm2_runtime_check.cpp index 94ab9ae..b97d37e 100644 --- a/tests/native/pvm2_runtime_check.cpp +++ b/tests/native/pvm2_runtime_check.cpp @@ -99,8 +99,8 @@ int main(int argc, char** argv) { assert(written == 123 && std::all_of(std::begin(boundary), std::end(boundary), [](uint8_t c) { return c == 0xa5; })); const auto plain = image(); std::vector code; - u16(code, 4); u16(code, 1); u32(code, 8); u32(code, 2); u16(code, argc > 1 && std::string(argv[1]) != "block-before-init" ? 188 : 98); - for (int i = 0; i < (argc > 1 && std::string(argv[1]) != "block-before-init" ? 188 : 98); i++) { + u16(code, 4); u16(code, 1); u32(code, 8); u32(code, 2); u16(code, argc > 1 && std::string(argv[1]) != "block-before-init" ? 189 : 98); + for (int i = 0; i < (argc > 1 && std::string(argv[1]) != "block-before-init" ? 189 : 98); i++) { auto bytes = plain; if (i >= 98) { std::ifstream input(std::string(argv[1]) + "/image" + std::to_string(i - 98) + ".bin", std::ios::binary); @@ -204,6 +204,11 @@ int main(int argc, char** argv) { assert(JNI_CreateJavaVM(&jvm, reinterpret_cast(&env), &args) == JNI_OK); jobject result = interpret(env, 2, 0, nullptr); assert(result && !env->ExceptionCheck()); + jobject wideResult = interpret(env, 2, 188, nullptr); + assert(wideResult && !env->ExceptionCheck()); + jclass longCls = env->FindClass("java/lang/Long"); + assert(env->CallLongMethod(wideResult, env->GetMethodID(longCls, "longValue", "()J")) == -2147483648LL); + env->DeleteLocalRef(wideResult); auto check_error = [&](const char* type, const char* message) { assert(env->ExceptionCheck()); jthrowable error = env->ExceptionOccurred(); env->ExceptionClear(); diff --git a/third_party/xopprotector/packer/src/main/java/com/yqsh/protector/packer/Pvm2Compiler.java b/third_party/xopprotector/packer/src/main/java/com/yqsh/protector/packer/Pvm2Compiler.java index 74c44bb..3e5ebd0 100644 --- a/third_party/xopprotector/packer/src/main/java/com/yqsh/protector/packer/Pvm2Compiler.java +++ b/third_party/xopprotector/packer/src/main/java/com/yqsh/protector/packer/Pvm2Compiler.java @@ -416,8 +416,10 @@ private static int translateOne(Dex dex, short[] units, int pc, int op, String d return 2; } case 0x17: { - long imm = (units[pc + 1] & 0xffffL) | ((units[pc + 2] & 0xffffL) << 16); - emits.add(Emit.const64((u0 >> 8) & 0xff, imm)); + // const-wide/32 的 32 位立即数必须按有符号 int 扩展到 long; + // 否则 -2147483648 会变成 +2147483648,Integer.MIN_VALUE 边界判断会失败。 + int imm32 = (units[pc + 1] & 0xffff) | ((units[pc + 2] & 0xffff) << 16); + emits.add(Emit.const64((u0 >> 8) & 0xff, imm32)); return 3; } case 0x18: { // const-wide diff --git a/tools/xop-pvm2-packer.jar b/tools/xop-pvm2-packer.jar index d658864..e1a0a44 100644 Binary files a/tools/xop-pvm2-packer.jar and b/tools/xop-pvm2-packer.jar differ